在打字稿中使用联合类型时,如何防止分配错误?

时间:2019-04-25 08:59:18

标签: typescript typescript-typings

想象一下我有以下接口:

   interface FirstElement {
      id: string;
      coordinates: Coordinates;
      type: FirstElementTypes;
      options: FirstElementOptions;
    }

   interface SecondElement {
      id: string;
      coordinates: Coordinates;
      type: SecondElementTypes;
      options: SecondElementOptions;
    }

    interface FirstElementDTO {
      id: string;
      type: FirstElemenTypes;
      options: FirstElementOptions;
    }

    interface SecondElementDTO {
      id: string;
      type: SecondElementTypes;
      options: SecondElementOptions;
    }

现在,我想创建一个DTO对象,将这些接口映射到其对应的DTO接口。因为它们共享相同的属性,只是选项不同,所以我想使用一个转换器函数。但是,当使用打字稿联合键入时...

  private static convertElementToDTO(element: FirstElement | SecondElement): FirstElementDTO | SecondElementDTO {
    return {
      id: element.id,
      options: element.options,
      type: element.type
    };
  }

...我(很明显)收到一条错误消息,告诉我这些选项不兼容。在打字稿中是否可以“讲述”一个函数,如果FirstElement是输入类型,FirstElementDTO是输出类型,反之亦然SecondElement-无需多次编写相同的代码并使用几个if语句?谢谢你的帮助!

1 个答案:

答案 0 :(得分:1)

generic函数可能在这里起作用。首先,一些虚拟类型定义使此处的代码成为独立的示例:

type FirstElementTypes = { FirstElementTypes: true };
type FirstElementOptions = { FirstElementOptions: true };
type SecondElementTypes = { SecondElementTypes: true };
type SecondElementOptions = { SecondElementOptions: true };

然后我们可以用这种方式表示您的类型,以减少代码重复:

// your types
interface FirstElementDTO {
  id: string;
  type: FirstElementTypes;
  options: FirstElementOptions;
}

interface SecondElementDTO {
  id: string;
  type: SecondElementTypes;
  options: SecondElementOptions;
}

// define elements as extension of DTOs to reduce code duplication
interface FirstElement extends FirstElementDTO {
    coordinates: Coordinates;
}

interface SecondElement extends SecondElementDTO {
    coordinates: Coordinates;
}

最后是通用函数:

// generic Pick function
function convertElementToDTO<E extends FirstElement | SecondElement>(
  element: E
): Pick<E, "id" | "options" | "type"> {
  return {
    id: element.id,
    options: element.options,
    type: element.type
  };
}

它可以正常工作:

declare const f: FirstElementTypes;
declare const o: FirstElementOptions;
declare const c: Coordinates;
const first: FirstElementDTO = convertElementToDTO({
  id: "firstEl",
  type: f,
  coordinates: c,
  options: o
}); // okay

Playground link

希望有所帮助;祝你好运!