Typescript泛型可用于扩展接口(interface)。
interface Sample1<P> {
prop1: P;
}
interface Sample2<P> extends Sample1<P> {
prop2: string;
}
但是,当我尝试创建使用通用接口(interface)的功能组件时, typescript 会引发错误。
const SampleSFC: React.SFC<Sample2<P>> = () => <div />;
如果我将
P
替换为string
这样的已知类型,错误就会消失。const SampleSFC: React.SFC<Sample2<string>> = () => <div />;
我想让
P
的用户设置SampleSFC
的类型,而不是完全杀死泛型的目的的P
的硬编码类型。我怎样才能做到这一点?如果不可能,那么我应该遵循哪种替代设计,这将使我拥有带有通用 Prop 的SFC。
最佳答案
泛型类型变量可以在函数和类型声明中使用,例如接口(interface)Sample1
和Sample2
。
但是,当您实际使用/调用/调用泛型类型时,必须指定一个具体的类型参数,而不是P
。React.SFC
(无状态函数组件类型)是接口(interface)声明,因此在const
分配中使用它需要P
的具体类型。
我想到的唯一解决方案是使ts-compiler的SFC
看起来像function
类型,因为函数声明/表达式可以
被分配泛型类型参数。有关示例,请参见Typescript docs。
证监会的一般声明
在您的分配React.SFC
中省略const SampleSFC
类型注释:
const SampleSFC = <P extends {}>(props: Sample2<P>) => <div>{props.prop1} </div>;
这样,您的组件仍然是普通函数。如果您需要
React.SFC
中的其他成员,请将它们添加到 Prop 中。例如。如果需要children
:const SampleSFC = <P extends {}>(props: Sample2<P> & { children?: ReactNode })
=> <div >{props.prop1} </div>;
SFC的一般用法
从Typescript 2.9开始,可以在JSX中直接设置type参数。
const MyApp: React.SFC<{}> = (props) => {
return <SampleSFC<number> prop2="myString" prop1={1} />
}
备择方案
1.)如果您不喜欢这些怪癖,那么切换到类组件将很容易。
class SampleSFCClass<P> extends React.Component<Sample2<P>> {
render() {
return <div>{this.props.prop1}</div>
}
}
const MyApp2: React.SFC<{}> = (props) => {
return <SampleSFCClass<number> prop2="myString" prop1={1} />
}
2)您甚至可以将
SFC
包装在另一个函数中。const withGeneric: <P>() => React.SFC<Sample2<P>> = <P extends {}>() => {
return (props) => <div> {props.prop1} {props.prop2} </div>;
}
const SampleSFCCalled: React.SFC<Sample2<string>> = withGeneric<string>();
const MyApp: React.SFC<{}> = (props) => {
return <SampleSFCCalled prop2="myString" prop1="aString" />
}
它将起作用,但是缺点可能是性能略有下降,因为
SFC
函数始终在父组件的每个渲染周期中重新创建。泛型的JSX/TSX兼容性问题:
在某些星座中,由于语法不明确,Typescript在与JSX/TSX(最新的3.0.1)结合使用时似乎无法解析泛型。编译错误将是:
建议在这种情况下使用
function
语法的贡献者之一(请参阅issue)。当您坚持使用箭头功能时,解决方法是让type参数从对象扩展(显示为here或here)以阐明其意图是通用lambda而不是JSX标签:
<P extends {}>
或<P extends object>
希望有帮助。