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)Sample1Sample2
但是,当您实际使用/调用/调用泛型类型时,必须指定一个具体的类型参数,而不是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参数从对象扩展(显示为herehere)以阐明其意图是通用lambda而不是JSX标签:
<P extends {}><P extends object>
希望有帮助。

10-06 04:04