Почему я не могу использовать значение в константе как определение пользовательского типа? - PullRequest
0 голосов
/ 12 февраля 2019

Это не компилируется

export const QuantityModes = {
    POSITIVE: 'POSITIVE', 
    NEGATIVE: 'NEGATIVE',
    ANY: 'ANY', 
};

export type QuantityMode = QuantityModes.POSITIVE | QuantityModes.NEGATIVE | QuantityModes.ANY;

Это компилируется

export const QuantityModes = {
    POSITIVE: 'POSITIVE',
    NEGATIVE: 'NEGATIVE',
    ANY: 'ANY',
};

export type QuantityMode = 'POSITIVE' | 'NEGATIVE' | 'ANY';

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Рассматривали ли вы вместо этого использование строкового перечисления?Это и тип (для компилятора TypeScript), и значение (объект псевдо-карты JavaScript, эквивалентный вашему const QuantityModes).Есть все еще некоторые ограничения, но это более удобно.

enum QuantityMode {
    POSITIVE = 'POSITIVE', 
    NEGATIVE = 'NEGATIVE',
    ANY = 'ANY', 
}

const a_ko: QuantityMode = 'POSITIVE';     // Error: Type '"POSITIVE"' is not assignable to type 'QuantityMode'
const a_ok_1 = QuantityMode.POSITIVE;      // Strict use
const a_ok_2 = 'POSITIVE' as QuantityMode; // Lax use

// Composable within an union type
type QuantityStrictMode = QuantityMode.POSITIVE | QuantityMode.NEGATIVE;

const b_ko  : QuantityStrictMode = 'POSITIVE';            // Error: Type '"POSITIVE"' is not assignable to type 'QuantityStrictMode'
const b_ok_1: QuantityStrictMode = QuantityMode.POSITIVE; // Strict use
const b_ok_2 = 'POSITIVE' as QuantityStrictMode;          // Lax use
0 голосов
/ 12 февраля 2019

Первая проблема, с которой вы столкнулись, заключается в том, что типом свойств на самом деле являются все string, а не строковые литералы, как вы могли ожидать.Чтобы исправить это, мы можем либо использовать утверждение типа:

export const QuantityModes = {
    POSITIVE: 'POSITIVE' as 'POSITIVE', 
    NEGATIVE: 'NEGATIVE' as 'NEGATIVE',
    ANY: 'ANY' as 'ANY', 
};

Использовать вспомогательную функцию для подсказки компилятору, что мы хотим получить литералы типа:

export const QuantityModes = (<T extends { [P in keyof T]: P }>(o: T)=> o)({
    POSITIVE: 'POSITIVE', 
    NEGATIVE: 'NEGATIVE',
    ANY: 'ANY', 
})

Или, начиная с версии 3.4 (не выпущенопока), вы можете написать as const:

export const QuantityModes = {
    POSITIVE: 'POSITIVE', 
    NEGATIVE: 'NEGATIVE',
    ANY: 'ANY', 
} as const

Вы можете ввести тип относительно другого типа, но синтаксис другой.Во-первых, если вы хотите получить доступ к типу свойства, синтаксис будет type['propName'] (также называемый запрос типа индекса ).Но вы хотите получить доступ к типу константы, для этого вам нужно использовать typeof const.Таким образом, вы можете написать:

export type QuantityMode = typeof QuantityModes["POSITIVE"] | typeof QuantityModes["NEGATIVE"] | typeof QuantityModes["ANY"];

Вы также можете использовать объединение для упрощения с тем же результатом:

export type QuantityMode = typeof QuantityModes["POSITIVE" | "NEGATIVE" | "ANY"];

Если объединение содержит все имена свойств, то мы можем просто использоватьkeyof type для получения объединения всех имен свойств в типе (гарантируя, что все будущие добавления также автоматически добавляются в тип)

export type QuantityMode = typeof QuantityModes[keyof typeof QuantityModes];

Поскольку в этом случае имя свойства и тип свойства совпадаютмы могли бы просто использовать keyof:

export type QuantityMode = keyof typeof QuantityModes;
...