Как преобразовать интерфейс в массив конкретных интерфейсов

У меня есть объект с 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[]
}

Один из атрибутов - строка / логическое значение, а другой - строка / число?

Frank Modica 31.10.2018 14:06
key - это имя атрибута, value - значение атрибута. Тип value зависит от key. Это может быть любой
Microshine 31.10.2018 14:16

Вы намерены разрешить добавление attr1 к объекту несколько раз?

Ian MacDonald 31.10.2018 14:33
0
3
1 636
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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,
    },
  }
}

Другие вопросы по теме