reactjs - 我可以创建一个继承另一个 prop 的泛型类型的 prop 吗?
问题描述
我正在使用 TypeScript 编写一个 React 项目,并且我想创建一个新组件,该组件接受一个对象数组的值,并且可以创建新对象以添加到该数组中。创建新对象时,我希望它从我定义的蓝图开始,其中已经包含一些对象字段的默认值。
我的问题是我似乎无法让蓝图遵循值的通用类型。根据 TypeScript,以下(非常简化的示例)代码非常好:
type Props<T extends object> = {
value: Array<T>;
blueprint: T;
};
function MyComponent<T extends object>({}: Props<T>) {
return <div></div>;
}
function ParentComponent() {
return <MyComponent
value={[{ foo: "bar" }, { foo: "oof"}]}
blueprint={{ boo: "faz" }} // This doesn't throw a type-error, but I would like it to.
/>
}
blueprint
当道具看起来不像数组中的对象时,我希望 TypeScript 引发类型错误value
。我已经尝试通过使用扩展或等于第一个的第二个泛型类型来做到这一点,但我没有设法找到解决方案。
解决方案
默认情况下,编译器将从属性和属性进行推断T
,value
通常blueprint
作为从每个属性推断的类型的联合。但是您希望编译器仅从中推断T
并value
验证是否匹配blueprint
。换句话说,您希望T
inblueprint
成为非推理类型参数用法,如microsoft/TypeScript#14829中所建议的那样。
此功能尚未得到正式支持,但有几种方法可以实现此行为。第一个是通过与近乎顶级的类型相交来“降低属性T
中的推理优先级” :blueprint
{}
type NoInfer<T> = T & {};
type Props<T extends object> = {
value: Array<T>;
blueprint: NoInfer<T>;
};
另一种方法是使用条件类型延迟来防止发生推理:
type NoInfer<T> = [T][T extends any ? 0 : never];
type Props<T extends object> = {
value: Array<T>;
blueprint: NoInfer<T>;
};
在任一版本中,blueprint
最终都被评估为 type T
(或 Nearly T
),但推理要么被延迟,要么被阻止。这两个版本都为您的示例提供了以下行为:
function ParentComponent() {
return <MyComponent
value={[{ foo: "bar" }, { foo: "oof" }]}
blueprint={{ boo: "faz" }} // error!
// Type '{ boo: string; }' is not assignable to type '{ foo: string; }'.
/>
}
这就是你想要的。
不确定是否值得做这些变通办法,因为它们可能在更广泛的代码库中存在一些可观察到的问题或边缘情况。这可能由您来决定您的用例有多严重需要无推断。好的,希望有帮助;祝你好运!
推荐阅读
- css - 如何使具有不同左/右填充的弹性项目具有相同的宽度?
- python - 我可以在 Python 的 azure 函数中使用绑定表达式吗?
- jasper-reports - 我可以限制 Jasper PDF 被 Adobe 等第三方软件编辑吗
- c - 如何获取 oracle 类型 NUMBER 作为字符串或 int/uint?
- python - django datefield 迁移给出错误
- r - 将多个excel工作表合并到r中的一个公共数据框中,不包括一些工作表
- java - Eclipse for Java 每小时卡住一次
- javascript - 如何使用jquery在全屏模式下打开新页面而不刷新
- python - 为什么循环不会通过任何按键来停止?
- css - 使用反应路由器哈希链接的移动设备上的锚点 ID 不准确