【发布时间】:2021-10-07 13:53:13
【问题描述】:
考虑这个检索“项目”或“项目”数组的函数:
function foo<T extends Item | Item[]>(id: T extends Item ? string : undefined): T {
...
}
这样做的目的是,如果您想要单个项目,则使用 id 调用 foo,如果您想要一组项目,则使用 id 而不使用 id。这很有效,因此调用者可以这样做:
foo<MyItem>('42')
和
foo<MyItem[]>(undefined)
(可以使用诸如function foo<T extends Item | Item[]>(...[id]: T extends Item ? [string] : []): T { 之类的可变参数来更好地实现这一点,以便在检索数组时启用不带参数调用foo。
但是,在foo 的实现中,我注意到如果我检查id 的类型:
if (id) { // if typeof id === 'string' gives same result
...
}
...然后在那个 if 子句中,编译器不理解类型 T 现在必须扩展 Item 并且 not Item[] (由于 id 是一个字符串仅当 T extends Item 时。如果我想调用任何依赖于 T 为 Item 的代码,我仍然需要执行 T as Item,否则我会得到:
TS2344: Type 'T' does not satisfy the constraint 'Item'. Type 'Item | Item[]' is not assignable to type 'Item'. Property 'id' is missing in type 'Item[]' but required in type 'Item'.
换句话说,id 的类型以T 的类型为条件,但 T 的类型不会通过断言 id 是一个字符串来推断/缩小。
有可能以某种方式解决这个问题吗?这是一个简单的as 演员阵容,但我只是好奇。
【问题讨论】:
-
有关信息,请参阅 the GitHub issues linked here。您不能通过检查
id来缩小T,因为T可能是完整的Item | Item[]联合。你想说“T extends ItemORT extends Item[]”而不是T extends Item | Item[],但是 TS 中没有表达这一点的工具。如果您不担心这种可能性,您应该只使用类型断言来抑制错误。 -
我认为最好避免异类联合。但这只是我的意见
标签: typescript typescript-generics