Почему вывод кортежа из любого [] становится [string, string, ...], а из string [] становится ['literal1', 'literal2', ...] - PullRequest
0 голосов
/ 20 декабря 2018

Я прочитал этот ответ https://stackoverflow.com/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[] кортеж имеет строковые типы (не литералы).

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'.Разрешает ли вывод типа только один шаг?

1 Ответ

0 голосов
/ 20 декабря 2018

Это не обязательно для кортежей.Typescript выведет литеральный тип для универсального параметра, если параметр типа имеет ограничение, которое может иметь литеральные типы.Это поведение было введено этим PR

От PR:

Во время вывода аргумента типа для выражения вызова тип, выведенный для параметра типа T, расширенк его расширенному литеральному типу, если [...] T не имеет ограничений или его ограничение не включает примитивные или литеральные типы

В примере из вашего вопроса, поскольку string является примитивным,мы не расширяемся, и поскольку any не является примитивным, мы расширяемся.

...