当前位置: 首页 > 知识库问答 >
问题:

通用无状态组件的类型?或者在typescript中扩展泛型函数接口以获得进一步的泛型?

刘星火
2023-03-14

问题:无状态函数组的接口给出为

interface SFC<P = {}> {
    (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null;
    propTypes?: ValidationMap<P>;
}

我的组件的prop类型也是通用的:

interface Prop<V>{
    num: V;
}

如何正确定义我的组件?作为:

const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>

在字符27处出现错误,找不到名称“T”

下面是修改后的示例的Typescript

我的调查结果:

1: TypeScript 2.9.1支持有状态通用组件:http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#generic-type-arguments-in-jsx-elements

class myCom<T> extends React.Component<Prop<T>, any> {
   render() {
      return <div>test</div>;
   }
}

2:扩展SFC以创建一个新接口,如以下答案所述,将使组件的prop类型为any:Typecript React无状态函数,具有我不想要的通用参数/返回类型。我想给我的道具适当的类型

共有3个答案

程鸿煊
2023-03-14

工厂模式:

import React, { SFC } from 'react';

export interface GridProps<T = unknown> {
  data: T[];
  renderItem: (props: { item: T }) => React.ReactChild;
}

export const GridFactory = <T extends any>(): SFC<GridProps<T>> => () => {
  return (
    <div>
      ...
    </div>
  );
};

const Grid = GridFactory<string>();

要避免钩子错误规则,必须使用如下语法:

import React, { FC } from 'react';

export interface GridProps<T = unknown> {
  data: T[]
  renderItem: (props: { item: T }) => React.ReactChild
}

export const GridFactory = <T extends any>() => {
  const Instance: FC<GridProps<T>> = (props) => {
    const [state, setState] = useState(props.data)

    return <div>...</div>
  }

  return Instance
}

const Grid = GridFactory<string>()
澹台锐
2023-03-14

有一种模式可以通过在组件外部声明通用组件类型别名,然后在需要时简单地断言它来缓解此问题。

虽然没有那么漂亮,但仍然是可重用的和严格的。

interface IMyComponentProps<T> {
  name: string
  type: T
}

// instead of inline with component assignment
type MyComponentI<T = any> = React.FC<IMyComponentProps<T>>

const MyComponent: MyComponentI = props => <p {...props}>Hello</p>

const TypedComponent = MyComponent as MyComponentI<number>
萧霍英
2023-03-14

不能像这样使用泛型:

const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>

TypeScript规范说明:

形式的构造

< T > ( ... ) => { ... }

可以解析为带有类型参数的arrow函数表达式或应用于不带类型参数的arrow函数的类型断言。

来源Microsoft/TypeScript spec.md

您的声明与TypeScript规范中定义的模式不匹配,因此无法工作。

然而,您可以不使用证监会界面,只需自己声明。

interface Prop<V> {
    num: V;
}

// normal function
function Abc<T extends string | number>(props: Prop<T>): React.ReactElement<Prop<T>> {
    return <div />;
}

// const lambda function
const Abc: <T extends string | number>(p: Prop<T>) => React.ReactElement<Prop<T>> = (props) => {
   return <div />
};

export default function App() {
    return (
        <React.Fragment>
            <Abc<number> num={1} />
            <Abc<string> num="abc" />
            <Abc<string> num={1} /> // string expected but was number
        </React.Fragment>
    );
}
 类似资料:
  • 问题内容: 您如何进行这项工作: 不做 编辑 为什么这不起作用? 我正在将编译器消息标记为错误。 问题答案: Reimeus已经指出,您在编辑中要求的内容是不可能的。我只想扩展一下原因。 人们会认为您可以使用以下内容: 实际上,这就是我第一次看到这篇文章时想到的。但这实际上会导致编译器错误: 类型变量不能跟其他界限 为了帮助我解释原因,我想引用Victor Rudometov在OracleBlog

  • 问题内容: 我正在尝试重构M类型确实扩展了任何内容的类和子类集,即使我们知道它必须是某种类型的子类也是如此。该类型已参数化,我希望其参数化类型可用于已经具有M值的子类。 有什么方法可以定义此类,而不必在参数列表中包括冗余的K和V泛型类型。我希望能够使编译器从子类映射到的M中推断出它们。 换句话说,我希望类声明看起来像这样: 从M的定义可以推断出K和V的类型。 问题答案: 问题在于,它们并没有真正地

  • 问题内容: 为了减少类的依赖性,我想将参数(使用泛型类)发送到扩展某些类并实现接口的构造函数,例如 可能吗? 此外,使用T类,我想使用T.getActivity()作为Context创建视图。 问题答案: T必须扩展Fragment并实现SomeInterface 在这种情况下,您可以声明以下内容: 这将需要扩展和实现类型的对象。 此外,使用T类,我想使用T.getActivity()作为Cont

  • 我想实现一个简单的排序函数,排序列表并返回排序列表(非常容易!)。所以我写了这个 问题是,当我试图对一个简单的列表排序时,它会给我带来这样的错误 那有什么问题?! 提前感谢:)))

  • 如何为动态创建的函数声明泛型类型? 我如何在中使用并传递? < code>useFoo的预期用法

  • 我不想为每个类型T编写这个方法只是为了调用getMessage()并将其传递给下一个方法。 有可能写出这样的方法吗?我只想访问ConstraintViolation接口的方法,这些方法不依赖于类型T(如字符串getMessage())。