javascript - 对象的类型为 'unknown'。ts(2571) 在通用组件中
我有一个带有泛型的表格组件,并且我在表格内部使用一个静态组件来组成列,这个静态组件也使用泛型。
问题是,我希望 Column 组件在执行 data 函数时继承传递给 Table 的通用类型,该函数会接收传递给它的结果。
我知道显式打字会起作用,例如:
<Table.Column<TableItem> data={(item) => item.name} />真正的问题是:是否有可能从我的 Table 组件执行这种类型推断,并将其传递给静态的 Column 组件?这样我就不必为每一列显式地添加类型……
用于重现的沙箱,仅限表和列组件:
https://codesandbox.io/s/generic-table-column-r54lh?file=/src/App.tsx
答案#1
你可以为 item 指定类型:
<Table.Column<TableItem> data={(item:[type goes here]) => item.name} />
一些例子:
<Table.Column<TableItem> data={(item:any) => item.name} />
// or even
<Table.Column<TableItem> data={(item:{name:string;}) => item.name} />
答案#2
你的 children 类型存在一个问题,也就是你使用了 ReactElement,它不包括对实际 JSX 函数的类型定义,只包含返回的元素。你可以在你的示例中看到这一点,通过注意以下协变和逆变的 children 都能通过,尽管你的 children 类型如此定义:
const MyDiv = (props:{myProp:string})=><div>{props.myProp}</div>
const App = () => {
return (
<Table<TableItem> keyExtractor={(item) => item.id} values={items}>
<Table.Column header="Name" data={(item) => item.name} />
<Table.Column header="Surname" data={(item) => item.surname} />
<MyDiv myProp="me" />
<div />
</Table>
);
};
但是……我认为这并不是真正影响你的根本问题。真正的问题是你希望 TypeScript 检查你的子组件是否确实是通过具体的 JSX 和具体的 props 创建的,但事实上,TypeScript 当前唯一会做的就是检查你的 JSX 返回的是一个有效的 JSX.Element。它不会检查生成该 JSX.Element 的函数是否符合某种类型,也不会检查该函数的返回类型是否是具有特定 props 的特定类型的元素。
这是在这个公开问题中讨论的设计限制。
我认为你可以通过本质上定义你自己的自定义 prop 来解决这个问题,该 prop 接收 Table.Column 的 props,然后将它们传递给你的 Table 组件中的 Table.Column。例如,可以像 columnProps: ColumnProps<T> 这样作为 Table 的一个 prop。不过,我不确定这是否会比直接为 Table.Column 提供显式类型更容易。
