为什么我不能使用常量中的值作为自定义类型定义?

Why cannot I use value in constant as custom type definition?

这是不可编译的

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';

您遇到的第一个问题是属性的类型实际上都是 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'](也称为 index type query)。但是你想访问常量的类型,为此你需要使用 typeof const。所以你可以写:

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

你也可以使用 union 来简化一点,结果相同:

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;

您是否考虑过改用字符串枚举?它既是一个类型(对于 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