如何创建接受泛型的无状态功能组件?

2024-03-29

Typescript 泛型可用于扩展接口。

interface Sample1<P> {
  prop1: P;
}

interface Sample2<P> extends Sample1<P> {
  prop2: string;
}

但是当我尝试创建一个使用通用接口的功能组件时,打字稿会抛出错误。

const SampleSFC: React.SFC<Sample2<P>> = () => <div />;

错误 TS2304:找不到名称“P”。

如果我更换P与已知类型类似string错误消失。

const SampleSFC: React.SFC<Sample2<string>> = () => <div />;

而不是硬编码类型P,这完全扼杀了泛型的目的,我想让用户能够SampleSFC设置类型P.

我怎样才能做到这一点?如果不可能,那么我应该遵循什么替代设计才能让我拥有带有通用道具的 SFC。


通用类型变量可以在函数和类型声明中使用,就像接口一样Sample1 and Sample2。 但是当您实际使用/调用/调用泛型类型时,您必须指定一个具体类型参数而不是P.

React.SFC- 无状态函数组件类型 - 是一个接口声明,因此在const赋值需要一个具体类型P.

我想到的唯一解决方案是SFC看起来像一个functionts 编译器的类型,因为函数声明/表达式可以 被分配泛型类型参数。看打字稿文档 https://www.typescriptlang.org/docs/handbook/generics.html举一些例子。

证监会通用声明

省略React.SFC在作业中键入注释const SampleSFC:

const SampleSFC = <P extends {}>(props: Sample2<P>) => <div>{props.prop1} </div>;

注:<P extends {}>由于 JSX/TSX 兼容性,需要该部分 泛型问题,请参阅本文末尾。

这样,您的组件仍然是一个简单的函数。如果您需要来自的额外成员React.SFC,将它们添加到您的道具中。例如。如果children needed:

const SampleSFC = <P extends {}>(props: Sample2<P> & { children?: ReactNode })
 => <div >{props.prop1} </div>;

通用 SFC 用法

Since 打字稿 2.9 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#generic-type-arguments-in-jsx-elements,类型参数可以直接在JSX中设置。

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)结合解析泛型时出现问题。编译错误将是:

“JSX 元素没有相应的结束标记。”

贡献者之一建议使用function在这种情况下的语法(参见issue https://github.com/Microsoft/TypeScript/issues/15713).

当您坚持使用箭头函数时,解决方法是让类型参数从对象扩展(如图所示)here https://medium.com/@jrwebdev/react-higher-order-component-patterns-in-typescript-42278f7590fb or here https://dev.to/danhomola/react-higher-order-components-in-typescript-made-simple)澄清它是一个通用的 lambda 而不是一个 JSX 标签:

<P extends {}> or <P extends object>

希望,这有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建接受泛型的无状态功能组件? 的相关文章

随机推荐