Ответ 1
ОБНОВЛЕНИЕ февраль 2019
В TypeScript 3.4, который должен быть выпущен в марте 2019 года, можно будет указать компилятору выводить тип кортежа литералов как кортеж литералов, а не как, скажем, string[]
, используя синтаксис as const
, Утверждение этого типа заставляет компилятор выводить наиболее узкий тип, возможный для значения, в том числе делая все доступным только для readonly
. Это должно выглядеть так:
const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
Это избавит от необходимости использовать вспомогательные функции любого рода. Удачи снова всем!
ОБНОВЛЕНИЕ июль 2018
Похоже, начиная с TypeScript 3.0, TypeScript сможет автоматически выводить типы кортежей. После того как функция tuple()
будет выпущена, ее можно кратко записать так:
export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;
И тогда вы можете использовать это так:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
Надеюсь, что это работает для людей!
ОБНОВЛЕНИЕ декабрь 2017
Поскольку я опубликовал этот ответ, я нашел способ определить типы кортежей, если вы хотите добавить функцию в свою библиотеку. Проверьте функцию tuple()
в tuple.ts. Используя его, вы можете написать следующее и не повторять себя:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
Удачи!
ОРИГИНАЛ июль 2017
Одной из проблем является то, что литерал ['a','b','c']
будет выводиться как string[]
типа string[]
, поэтому система типов забудет о конкретных значениях. Вы можете заставить систему типов запомнить каждое значение в виде буквенной строки:
const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
Или, может быть, лучше, интерпретировать список как тип кортежа:
const list: ['a','b','c'] = ['a','b','c']; // tuple
Это раздражает повторение, но, по крайней мере, оно не вводит посторонний объект во время выполнения.
Теперь вы можете получить свой союз следующим образом:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.
Надеюсь, это поможет.