如何将接口转换为特定接口的数组

时间:2018-10-31 12:45:44

标签: typescript

我的对象中包含attributes。每个属性都有属性列表,其值类型取决于键值。我正在尝试创建用于将属性类型的接口转换为我的结构的通用类型

这是我当前代码的示例。我无法为attributes设置类型。

interface IAttribute<Key, Value> {
  key: Key;
  value: Value;
  approved?: boolean;
  published?: boolean;
  fromPrototype?: boolean;
}

interface IObject<T> {
  id: string;
  attributes?: Array<IAttribute<K, T[K]>>; // K extends keyof T. How can I fix it?
}

interface ICustomAttributes {
  attr1: boolean;
  attr2: number;
}

type ICustom = IObject<ICustomAttributes>;

const o: ICustom = {
  id: "1",
  attributes: [
    {
      key: "attr1",
      value: true,
    },
    {
      key: "attr2",
      value: 123,
    },
  ],
}

最终结果必须像

type ICustomAttributes = IAttribute<"attr1", boolean> | IAttribute<"attr2", number>;

interface ICustom {
  id: string;
  attributes?: ICustomAttributes[]
}

1 个答案:

答案 0 :(得分:1)

您可以使用映射类型将类型的属性转换为IAttribute的并集:

interface IAttribute<Key, Value> {
  key: Key;
  value: Value;
  approved?: boolean;
  published?: boolean;
  fromPrototype?: boolean;
}



interface IObject<T> {
  id: string;
  attributes?: Array<{ [P in keyof T]: IAttribute<P, T[P]> }[keyof T]>; // K extends keyof T. How can I fix it?
}

interface ICustomAttributes {
  attr1: boolean;
  attr2: number;
}

type ICustom = IObject<ICustomAttributes>;

const o: ICustom = {
  id: "1",
  attributes: [
    {
      key: "attr1",
      value: true,
    },
    {
      key: "attr2",
      value: 123,
    },
  ],
}

但是,这不能确保每个成员至少出现一次且没有重复。根据您的用例,这可能是问题,也可能不是问题。如果您需要确保一次更好地使用对象而不是数组,则每个成员都完全存在(使用元组可以达到类似的效果,但是将对象类型转换为所有可能的元组的并集将需要使用递归类型不推荐使用的别名)

interface IObject<T> {
  id: string;
  attributes?: { [P in keyof T]: IAttribute<P, T[P]> }
}

interface ICustomAttributes {
  attr1: boolean;
  attr2: number;
}

type ICustom = IObject<ICustomAttributes>;

const o: ICustom = {
  id: "1",
  attributes: {
    "attr1": {
      key: "attr1",
      value: true,
    },
    "attr2": {
      key: "attr2",
      value: 123,
    },
  }
}