条件类型声明

时间:2019-05-16 05:20:09

标签: typescript typescript-typings

我不确定是否可以执行此操作,但是我想知道是否可以根据接口的键值(类型是枚举)来有条件地选择同一接口的另一个键是什么类型。将。我想如果没有示例,您不会理解的,所以,我们开始吧。

我有一些类型声明,基本上像这样:

interface BookingTextInput {
  type: InputType.text;
  metadata: TextInputMetadata;
}

interface BookingSelectInput {
  type: InputType.selectGrid;
  metadata: SelectInputMetadata;
}

interface BookingNumberInput {
  type: InputType.number;
  metadata: NumberInputMetadata;
}

type BookingInput = BookingTextInput | BookingNumberInput | BookingSelectInput;

我想做的是避免为每个InputType枚举值做一个接口,而是做一个BookingInput接口,该接口有条件地查看类型键中的值,并基于该值,它知道元数据密钥是什么类型。

2 个答案:

答案 0 :(得分:1)

您可以使用Type Guards。这是一个如何工作的小例子:

type Primitive = string | number | boolean;

function isString(x: Primitive): x is string {
    return typeof x === "string";
}

function isNumber(x: Primitive): x is number {
    return typeof x === "number";
}

function isBoolean(x: Primitive): x is boolean {
    return typeof x === "boolean";
}

let str: Primitive = "text";
let nmb: Primitive = 1;
let bln: Primitive = true;

let prms = [str, nmb, bln];

for (let x of prms) {
    if (isString(x)) {
        console.log(`string value: ${x}`);
    } else if (isNumber(x)) {
        console.log(`number value: ${x}`);
    } else if (isBoolean) {
        console.log(`boolean value: ${x}`);
    } else {
        console.log(`unknown type value: ${x}`);
    }
}

但是对于复杂类型,我建议像您的示例中那样使用联合类型。

答案 1 :(得分:1)

您可以使用接口将枚举类型映射到元数据接口,然后使用映射类型来获取功能上与您现在所拥有的并集的联合:

interface InputTypeToInterfaceMap {
  [InputType.text]: TextInputMetadata;
  [InputType.selectGrid]: TextInputMetadata;
  [InputType.number]: TextInputMetadata;
}

type BookingInput = { 
    [P in keyof InputTypeToInterfaceMap]: {
        type: P; metadata: InputTypeToInterfaceMap[P] 
    } 
}[keyof InputTypeToInterfaceMap];

这使代码更加简洁,您只需修改enum和映射接口即可添加新类型。

一种更简单的方法是根本不使用枚举。由于添加字符串文字类型,我发现对枚举的需求大大减少了。使用接口映射和简单的枚举并使用keyof来提取键的并集可以在添加新类型时以较少的更改实现相同类型的安全目标:

interface InputTypeToInterfaceMap {
    text: TextInputMetadata;
    selectGrid: TextInputMetadata;
    number: TextInputMetadata;
}

type InputType = keyof InputTypeToInterfaceMap //  "number" | "text" | "selectGrid"
type BookingInput = {
    [P in keyof InputTypeToInterfaceMap]: {
        type: P; metadata: InputTypeToInterfaceMap[P]
    }
}[keyof InputTypeToInterfaceMap];
相关问题