Typescript `custom type` работает только в мире типов, но фактически не работает с` function` - PullRequest
0 голосов
/ 23 марта 2019

У меня есть пользовательский тип с именем Tail , он будет возвращать тип массива без первого элемента:

type Tail<T extends any[]> =
    ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any)
    ? TT
    : []

type test11 = Tail<[1, 2, string, number]> // [2, string, number]

Приведенный выше код работает нормально, но при использовании с функцией это не такработает сейчас:

function tail<T extends any[]>(arr: T): Tail<T> {
  return arr.slice(1) as Tail<T>;
}

let result = tail(['', 1]); // res: (string | number)[]

enter image description here

Значение result должно быть только number, но вместо этого отображается (string | number)[], почему?

1 Ответ

1 голос
/ 23 марта 2019

См. Спецификация машинописи . В частности, он говорит:

Правила [дано] означают, что литерал массива всегда имеет тип массива, если только он не типизирован контекстно типом кортежа.

В вашем звонке на tail единственная подсказка для типа ['', 1] это any[]. (См. Раздел 4.15.2. Я просмотрел это и, кажется, это говорит, но кто-то может вызвать меня, если я ошибаюсь.) Поэтому его тип становится (string | number)[], и вы звоните tail с подписью

tail<(string | number)[]>(arr: (string | number)[]): (string | number)[]

Вы можете воспроизвести проблему как

let i = ['5', 5]
let x: [number] = tail(i)

И вы увидите, что оно исчезнет в

let i: [string, number] = ['5', 5]
let x = tail(i) // x: [number] (inferred)

Я полагаю, что вы просто не можете сделать вывод о типе кортежа в этой ситуации. Тем не менее, это должно быть хорошо, так как вы не должны передавать литералы в tail так часто.

...