我有一个组件,它接受一个项目列表,已知有一个 ID,以及一个过滤这些项目的函数。
具有 ID 的类型是项目的通用类型,所有项目都将具有。
但更具体的项目将包括其他道具。
type GenericItem = {
id: string;
}
type SpecificItem = {
id: string;
someOtherProp: boolean;
}
我还有一个函数类型,它使用泛型类型进行操作。
type GenericItemFunction = (item: GenericItem) => boolean;
然后,我有了这个在其 props 中使用 GenericItem 和 GenericItemFunction 的组件。
type CompProps = {
fn: GenericItemFunction;
items: GenericItem[];
}
const Comp: React.FC<CompProps> = ({ fn, items }) => <></>;
当我尝试将此组件与特定类型一起使用时,我收到错误消息,指出我无法使用 GenericItemFunction 的实现,因为项目的类型不兼容。
const App = () => {
const items: SpecificItem[] = [];
const filter = (item: SpecificItem) => item.someOtherProp;
return (
<Comp
fn={filter} // error on `fn` prop
items={items}
/>
)
}
我收到的打字稿错误是:
Type '(item: SpecificItem) => boolean' is not assignable to type 'GenericItemFunction'.
Types of parameters 'item' and 'item' are incompatible.
Property 'someOtherProp' is missing in type 'GenericItem' but required in type 'SpecificItem'.
我想我有两个问题;
首先,当两种类型都期望时,为什么会发生冲突id: string
财产?
其次,有没有更明智的方法来做这样的事情?
我的第一个是类型item
on the GenericItemFunction
可以从提供给的值推断出items
App 组件中的 prop。
但说实话,我不确定那会是什么样子......
我的另一个想法是Comp
是一个泛型,但没有显示使用使用泛型的 React 组件...似乎 jsx/tsx 并不真正支持该语法。
我希望这样的事情会引发各种错误。
const Comp = <T extends GenericItem,>({ fn, items }) => <></>;
const App = () => {
return <Comp<SpecificType> />;
}
最后我尝试了一下,没有出现任何错误。但缺点是类型items
被推断为任意。
type GenericItem = {
id: string;
}
type SpecificItem = {
id: string;
someOtherProp: boolean;
}
type GenericItemFunction <T> = (item: T) => boolean;
type CompProps <T extends GenericItem = any> = {
fn: GenericItemFunction<T>;
items: T[];
}
const Comp: React.FC<CompProps> = ({ fn, items }) => <></>;
const App = () => {
const items: SpecificItem[] = [];
const filter = (item: SpecificItem) => item.someOtherProp;
return (
<Comp
fn={filter}
items={items}
/>
)
}
这是我一直在使用的游乐场的链接。
https://www.typescriptlang.org/play?#code/C4TwDgpgBA4hB2EBOBLAxgSWBAtlAvFAN4BQAkCgCYBcUAzsKvAOYDcJAviSaJFAMqQ0KAGbosuAsRJRZUKrQZM2MuXQD2OCAHlgAC2QAFJOrC0ARuvUAbCAEN47Lj3DQ4iVJmw4AYgF d4NGAUdXgoAB4AFQA+KQAKFG9aSIBKAljLG3tHbhc+AGFNMGNTOgjIqAgAD2x4SjL3ZHFvKQcQWMJSMhF4WkbPCV8AoJD4KOj2OXlvOmSAbQBdJxI0UIYoQpwzKAAleyCAOh988M3ikzA6Dqg4oigegBpp3 DKONPxY8OjwgHoJ7lW8HWAEEwGB4u9YqQpoD1okXrRBBBhGIvLhFlJFpM5LDgPcUNZsEh4vCcIihKJmrhIc8cAcNFpdAYkCUwOxVLIkBBgH4kGE4hyphEzoKhXIevgiGJCcguGKxaS6JLFXL5X9BSlO EA https://www.typescriptlang.org/play?#code/C4TwDgpgBA4hB2EBOBLAxgSWBAtlAvFAN4BQAkCgCYBcUAzsKvAOYDcJAviSaJFAMqQ0KAGbosuAsRJRZUKrQZM2MuXQD2OCAHlgAC2QAFJOrC0ARuvUAbCAEN47Lj3DQ4iVJmw4AYgFd4NGAUdXgoAB4AFQA+KQAKFG9aSIBKAljLG3tHbhc+AGFNMGNTOgjIqAgAD2x4SjL3ZHFvKQcQWMJSMhF4WkbPCV8AoJD4KOj2OXlvOmSAbQBdJxI0UIYoQpwzKAAleyCAOh988M3ikzA6Dqg4oigegBpp3DKONPxY8OjwgHoJ7lW8HWAEEwGB4u9YqQpoD1okXrRBBBhGIvLhFlJFpM5LDgPcUNZsEh4vCcIihKJmrhIc8cAcNFpdAYkCUwOxVLIkBBgH4kGE4hyphEzoKhXIevgiGJCcguGKxaS6JLFXL5X9BSlOEA
UPDATE:
为什么使用 any 作为 GenericItem 类型的默认值?如果没有这个,我相信它应该正确地从 GenericItemFunction 推断出 Genericitem 。 – tymzap
删除= any
为了CompProps
typedef 导致错误Comp
宣言...
type CompProps <T extends GenericItem> = {
fn: GenericItemFunction<T>;
items: T[];
}
const Comp: React.FC<CompProps> = ({ fn, items }) => <></>; // this line has the error
Generic type 'CompProps' requires 1 type argument(s).
意思是,我仍然必须在某个地方声明类型。这意味着我需要知道的变化GenericItem
在使用该组件之前键入。
SpecificItem
只是恰好与以下类型重叠的类型的表示GenericItem
类型定义。
在大多数情况下,Comp
不知道实际使用什么类型,并且 any 不会向作者提供任何有用的信息。
我希望有类似的事情...
type CompProps <T extends GenericItem> = {
items: <T extends GenericItem>[];
fn: <infer from T>[];
}
但我不确定这是否存在,或类似的东西。