Ответ 1
Обновление июль 2018
Похоже, начиная с TypeScript 3.0, для TypeScript будет возможно автоматически выводить типы кортежей. После того, как это будет выпущено, tuple()
вам функцию tuple()
можно кратко записать так:
export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;
И тогда вы можете использовать это так:
const ALL_SUITS = tuple('hearts', 'diamonds', 'spades', 'clubs');
type SuitTuple = typeof ALL_SUITS;
type Suit = SuitTuple[number]; // union type
Обновление август 2017
Так как я опубликовал этот ответ, я нашел способ определить типы кортежей, если вы хотите добавить функцию в свою библиотеку. Проверьте функцию tuple()
в tuple.ts.
export type Lit = string | number | boolean | undefined | null | void | {};
// infers a tuple type for up to twelve values (add more here if you need them)
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit, H extends Lit, I extends Lit, J extends Lit, K extends Lit, L extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L): [A, B, C, D, E, F, G, H, I, J, K, L];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit, H extends Lit, I extends Lit, J extends Lit, K extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K): [A, B, C, D, E, F, G, H, I, J, K];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit, H extends Lit, I extends Lit, J extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): [A, B, C, D, E, F, G, H, I, J];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit, H extends Lit, I extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I): [A, B, C, D, E, F, G, H, I];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit, H extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): [A, B, C, D, E, F, G, H];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit, G extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F, g: G): [A, B, C, D, E, F, G];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit, F extends Lit>(a: A, b: B, c: C, d: D, e: E, f: F): [A, B, C, D, E, F];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit, E extends Lit>(a: A, b: B, c: C, d: D, e: E): [A, B, C, D, E];
export function tuple<A extends Lit, B extends Lit, C extends Lit, D extends Lit>(a: A, b: B, c: C, d: D): [A, B, C, D];
export function tuple<A extends Lit, B extends Lit, C extends Lit>(a: A, b: B, c: C): [A, B, C];
export function tuple<A extends Lit, B extends Lit>(a: A, b: B): [A, B];
export function tuple<A extends Lit>(a: A): [A];
export function tuple(...args: any[]): any[] {
return args;
}
Используя его, вы можете написать следующее и не повторять себя:
const ALL_SUITS = tuple('hearts', 'diamonds', 'spades', 'clubs');
type SuitTuple = typeof ALL_SUITS;
type Suit = SuitTuple[number]; // union type
Как вы думаете?
Оригинальный ответ
Самый простой способ получить то, что вы хотите - это явно указать тип кортежа и извлечь из него объединение, вместо того, чтобы пытаться заставить TypeScript сделать обратное, чего он не знает, как это сделать. Например:
type SuitTuple = ['hearts', 'diamonds', 'spades', 'clubs'];
const ALL_SUITS: SuitTuple = ['hearts', 'diamonds', 'spades', 'clubs']; // extra/missing would warn you
type Suit = SuitTuple[number]; // union type
Обратите внимание, что вы все еще пишете литералы дважды, один раз как типы в SuitTuple
и один раз как значения в ALL_SUITS
; вы не найдете там отличного способа избежать повторения себя таким образом, поскольку в настоящее время TypeScript нельзя сказать, чтобы выводить кортежи, и он никогда не сгенерирует массив времени выполнения из типа кортежа.
Преимущество здесь в том, что вы не требуете перечисления ключей фиктивного объекта во время выполнения. Конечно, вы можете создавать типы с костюмами в качестве ключей, если они вам все еще нужны:
const symbols: {[K in Suit]: string} = {
hearts: '♥',
diamonds: '♦',
spades: '♠',
clubs: '♣'
}
Надеюсь, это поможет.