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

Why does tuple inference from any[] become [string, string, ... ] and from string[] become ['literal1', 'literal2', ... ]

我已经阅读了这个答案 ,它演示了元组类型推断。经过一些实验,我遇到了这种情况。


当我们的 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 类型(不是文字)。

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

引入的

来自公关:

During type argument inference for a call expression the type inferred for a type parameter T is widened to its widened literal type if [...] T has no constraint or its constraint does not include primitive or literal types

在您问题的示例中,由于 string 是原始的,我们没有加宽,并且由于 any 不是原始的,我们确实加宽了。