Как ввести тип кортежа в качестве сопоставленного типа объекта или как создать тип объекта из списка ключей?

#typescript

Вопрос:

Итак, у меня есть система, в которой я использую атрибуты в виде символов.

 const A = Symbol.for(":a")
const B = Symbol.for(":b")
const C = Symbol.for(":c")

interface Attributes {
  [A]: string
  [B]: number
  [C]: boolean
}

const pattern_1 = [A, B]
const pattern_2 = [B, C]
 

Мне нужна функция, которая может определить тип объекта:

  • { [A]: string, [B]: number } От pattern_1 [A, B]
  • { [B]: number, [C]: boolean } От pattern_2 [B, C]

Я зашел так далеко

 type AttributeKeys ReadonlyArray<keyof Attributes>

declare function pattern<Pattern extends AttributeKeys>(...attrs: Pattern): Pattern

const PATTERN = pattern(A, B) // inferred type is [typeof A, typeof B]
 

Чего я не могу сделать, так это изменить тип кортежа на объект. На следующем шаге я хочу, чтобы он сделал вывод, что я верну объект с ключами из массива в качестве ключей в новом типе объекта. Я хочу, чтобы тип ключей соответствовал тому, который объявлен в Атрибутах. Это самое большое расстояние, которое я смог пройти:

 declare function pull1<T>(pattern: T): { [K in keyof T]: K extends keyof Attributes ? Attributes[K] : never }

const entity1 = pull1(PATTERN) // inferred type is [never, never]

declare function pull2<T>(pattern: T): { [K in keyof Attributes]: K extends T ? Attributes[K] : never }

const entity2 = pull2(PATTERN) // inferred type is { [A]: never, [B]: never, [C]: never }
 

Я не могу заставить это работать, нужна помощь! Вот ссылка на игровую площадку для машинописи, если кто-то думает, что сможет ее взломать.

пс. Я должен использовать символы, но все остальное-это просто то, что я пробовал. Если есть лучший способ, пожалуйста, поделитесь!

Комментарии:

1. Откуда функция получает значения свойств? Свойства объекта имеют не только типы, но и значения. Или вам просто нужен сопоставленный тип, а не функция?

2. Просто сопоставленный тип.

Ответ №1:

Вы можете просто использовать Pick предопределенные сопоставленные типы:

 
declare function pull2<T extends Array<keyof Attributes>>(pattern: T): Pick<Attributes, T[number]>

const entity2 = pull2(PATTERN)
let a = entity2[A] // string
let b = entity2[B] // number
entity2[C] // err
 

Ссылка на игровую площадку

Комментарии:

1. Отлично, спасибо!