我正在尝试弄清楚如何为Data条目编写正确的类型,以便它接受任何带有属性的组件
示例:
const A = (props: { a: number }) => <>{props.a}</>
const B = (props: { b: string }) => <>{props.b}</>
type Data = {
[id: string]: <P>(props: P) => JSX.Element | null
}
const data: Data = {
aa: (props: Parameters<typeof A>[0]) => A(props),
bb: (props: Parameters<typeof B>[0]) => B(props)
}
const Usage = () => (
<>
A: {data.aa({ a: 12 })}
B: {data.bb({ b: 'hi' })}
</>
)
即使我已经为每个组件指定了属性类型,我仍然收到以下错误:
TS2322: Type '(props: Parameters<typeof A>[0]) => JSX.Element' is not assignable to type '<P>(props: P) => Element | null'.
Types of parameters 'props' and 'props' are incompatible.
Type 'P' is not assignable to type '{ a: number; }'
我应该在Data
类型中写什么,这样它就可以接受任何组件?
2条答案
按热度按时间insrf1ej1#
如果您已经安装了
@types/react
和@types/react-dom
,则大多数React类型都已定义。功能组件的类型为
FunctionComponent
或FC
(简称)。它也是通用的,因此您可以指定属性类型。演示:https://stackblitz.com/edit/react-ts-y9ejme?file=App.tsx
但是注意,如果输入
Data
对象,你会丢失props类型,因为你允许任何props类型。Typescript不会看到b
应该是一个数字,而不是字符串。最好排除该类型,让typescript从对象文字中推断类型。演示:https://stackblitz.com/edit/react-ts-j8uagi?file=App.tsx
否则,必须显式键入属性:
演示:https://stackblitz.com/edit/react-ts-ykbq8q?file=App.tsx
或者,确保您正在访问的属性对所有组件都是通用的:
演示:https://stackblitz.com/edit/react-ts-atcwwh?file=App.tsx
还有其他选择,但这实际上取决于您的使用情形。
jmo0nnb32#
我喜欢Chris汉密尔顿提到的使用react中的函数组件类。我读到这个问题更多的是关于如何处理带约束的typescript泛型类型。我能看到的最好的方法是创建一个AProps和BProps的联合类型,用于在数据类型定义中定义类型约束,并使用typeguard强制每个数据函数中使用的内容。然而,如果您想让这种方法适用于任何类型的组件,那么它将变得很笨拙,因为您必须为所有可能的组件定义联合类型。