如何将正确的类型设置为已定义的对象键之一?

时间:2019-04-10 21:25:09

标签: typescript

我已经创建了此代码段来演示我的问题:

const typeEnum = {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5
};


const isCD = (...types: any[]) => {
    return types.some(t => {
        return t == typeEnum.c || t == typeEnum.d;
    });
};

console.log(
    isCD(
        typeEnum.a,
        typeEnum.b,
        typeEnum.d,
        6
    )
);

所以我想要将any[]替换为正确的类型,但是我不知道如何设置可接受的值是typeEnum键的值,所以没有人会通过{ {1}}作为参数,因为它不是可接受的参数。

TypeScript Playground link

谢谢。


我最后的工作片段以这种方式结束:

6

TypeScript Playground link

2 个答案:

答案 0 :(得分:1)

您无法从type定义const,但是可以定义const的类型。

此解决方案适合您的用例吗?

type AcceptedValue = 1 | 2 | 3 | 4 | 5;
const typeEnum : {[key: string]: AcceptedValue} = {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5
};

答案 1 :(得分:1)

对于TS3.4 +,您可以使用https://github.com/developit/preact-boilerplate告诉编译器,typeEnum的类型应推断为尽可能窄...属性值3将被推断为数字文字3而不是number

const typeEnum = {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5
} as const;
// inferred as type { readonly a: 1; readonly b: 2; readonly c: 3; 
//   readonly d: 4; readonly e: 5; }

如果尚未更新到TS3.4,则可以使用辅助功能获得类似的行为:

const litNumVals =
    <N extends number, T extends { [k: string]: N }>(t: T) => t;

const typeEnum = litNumVals({
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5
});
// inferred as type { a: 1; b: 2; c: 3; d: 4; e: 5; }

that 值开始,您可以使用类型函数来约束isCD参数:

type ValueOf<T> = T[keyof T]

type TypeEnumValues = ValueOf<typeof typeEnum>;
// 1 | 2 | 3 | 4 | 5    

const isCD = (...types: Array<TypeEnumValues>) => {
    return types.some(t => {
        return t == typeEnum.c || t == typeEnum.d;
    });
};

console.log(
    isCD(
        typeEnum.a, // okay
        typeEnum.b, // okay
        typeEnum.d, // okay
        6 // error
    )
);

好的,希望能有所帮助。祝你好运!