为什么来自 any[] 的元组推理变成了 [string, string, ...],而从 string[] 变成了 ['literal1', 'literal2', ... ]



我已经阅读了此答案https://stackoverflow.com/a/a/45486495/1108891,它演示了元组类型的推移。经过一些实验,我遇到了这种情况。


当我们的tuple函数具有T extends string[]时,元组具有字符串文字类型。

export const tuple_0 = <T extends string[]>(...args: T): T => args;
const ALL_SUITS_0 = tuple_0('hearts', 'diamonds', 'spades', 'clubs');
type T0 = typeof ALL_SUITS_0; // ["hearts", "diamonds", "spades", "clubs"]

另一方面,使用T extends any[],元组具有 String types(不是文字)。

export const tuple_1 = <T extends any[]>(...args: T) => args;
const ALL_SUITS_1 = tuple_1('hearts', 'diamonds', 'spades', 'clubs');
type T1 = typeof ALL_SUITS_1; // [string, string, string, string]

为什么我们在后一种情况下失去字面类型?


我怀疑这与类型推断允许自己采取的特异性步骤有关。也就是说,any距离string仅一步之遥,而string距离'some-string-literal'仅一步之遥。该类型的推理仅允许自己迈出一步吗?

这不是必需的元组。如果类型参数具有可以具有字面类型的约束,那么Typescript将推断为通用参数的字面类型。这种行为是由此pr

引入的

来自PR:

在呼叫表达式的类型参数推断期间,如果[...] T没有约束或约束不包括原始或文字类型

,则将类型参数t的类型扩大到其扩大的文字类型。

在您的问题中的示例中,由于string是原始的,我们不会扩大,并且由于any不是原始的,因此我们会扩大。

最新更新