我有一个接受泛型类型参数TChildProps
的组件:
type GenericFieldHTMLAttributes =
| InputHTMLAttributes<HTMLInputElement>
| SelectHTMLAttributes<HTMLSelectElement>
| TextareaHTMLAttributes<HTMLTextAreaElement>
interface FieldProps {
name: string
label?: string | React.ReactNode
component?: string | React.ComponentType
initialValue?: any
children?: React.ReactNode | FieldRenderFunction
}
class Field<TChildProps = GenericFieldHTMLAttributes> extends React.PureComponent<FieldProps & TChildProps> {
...
}
当我使用这个组件时,我希望它能阻止我传入无法识别的道具,例如:
render() {
return (
<Form onSubmit={this.save}>
<Field foo="test" label="email" name="email" type="email" component={TextField} />
</Form>
)
}
令人惊讶的是,尽管foo
道具未在任何地方定义,但上述代码甚至没有任何警告编译。我尝试简化示例并获得相同的结果:
class Field<TChildProps = {}> extends React.PureComponent<FieldProps & TChildProps> {
...
}
// this still compiles without errors
<Field foo="test" label="email" name="email" type="email" component={TextField} />
根据React.PureComponent
的类型定义(我在React.Component
上测试并获得相同的结果),TypeScript的运作方式与此相符,或者这是一个错误?
答案 0 :(得分:1)
原始答案
如果消费者未向<TChildProps = {}>
分配任何值,则TChildProps
表示默认值{}
为TChilProps
。因此,如果消费者决定将价值传递给它,TChildProps
实际上可以是任何东西。这就是为什么typescript允许任何道具传递给Field
的原因。您要做的是使用TChildProps
关键字强制执行extends
类型。所以请尝试使用class Field<TChildProps extends GenericFieldHTMLAttributes>
。因此,消费者需要将TChildProps
作为GenericFieldHTMLAttributes
类型传递。您可以在https://www.typescriptlang.org/docs/handbook/generics.html找到更多信息。
<强>更新强>
以下是简化情况( UPDATE2 :我倾向于认为这是一个错误或缺少的功能,这就是原因)
以下Animal
课程接受食物作为仿制品反映了React.Component
课程,它接受道具作为仿制品。
class Animal<F> {
eat(food: F) {
return;
}
}
以下Lion
类扩展Animal
反映了Field
类,其中React.Component
class Lion<F = {pizza: string}> extends Animal<F> {
}
当消费者食用它时,如果他们没有说明狮子应该吃什么食物,那么狮子可以吃任何类似食物我们应该期待狮子只吃披萨
const lion1 = new Lion();
lion1.eat(""); // Argument of type '""' is not assignable to parameter of type '{pizza: string}'
但是在tsx的情况下不会发生这种类型的检查。
解决方法是“将类型和接口别名为非泛型专业化。”
const TextField = Field as { new (): Field<{value: string}>};
<TextField foo="test" label="email" name="email" type="email" value="asdf"/> // error: Property 'foo' does not exist
这两个链接应该为您提供有关如何使用通用组件的更多信息。
https://github.com/Microsoft/TypeScript/issues/3960 https://basarat.gitbooks.io/typescript/docs/types/generics.html#generics-in-tsx
显然他们working on这个。
这应该可以在Typescript 2.9中实现,如https://github.com/Microsoft/TypeScript/pull/22415中所示。