【问题标题】:Why cannot I use value in constant as custom type definition?为什么我不能使用常量中的值作为自定义类型定义?
【发布时间】:2019-07-05 17:48:50
【问题描述】:

这是不可编译的

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

【问题讨论】:

    标签: typescript types constants typescript-typings custom-type


    【解决方案1】:

    您遇到的第一个问题是属性的类型实际上都是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;
    

    【讨论】:

    • 非常感谢您详细回答。每个 JS 开发者都应该在一定程度上学习进阶 TS
    • @tom10271 不能再同意了 :)
    【解决方案2】:

    您是否考虑过使用字符串枚举来代替?它既是类型(用于 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 2021-07-05
      • 1970-01-01
      • 2022-11-27
      • 1970-01-01
      • 2020-02-20
      • 2014-05-29
      相关资源
      最近更新 更多