Как написать тип PickByValue?

#typescript

#typescript

Вопрос:

Pick Тип включен в TypeScript. Его реализация заключается в следующем:

 type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};
  

Как бы вы написали PickByValue тип, чтобы работало следующее:

 type Test = {
  includeMe: 'a' as 'a',
  andMe: 'a' as 'a',
  butNotMe: 'b' as 'b',
  orMe: 'b' as 'b'
};

type IncludedKeys = keyof PickByValue<Test, 'a'>;
// IncludedKeys = 'includeMe' | 'andMe'
  

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

1. Вы хотите, чтобы PickByValue<Test, 'a' | 'b'> это было эквивалентно Test или эквивалентно {} ?

Ответ №1:

Предполагая, что вы намереваетесь Test быть таким:

 type Test = {
  includeMe: 'a',
  andMe: 'a',
  butNotMe: 'b',
  orMe: 'b'
};
  

и предполагая, что вы хотите PickByValue<T, V> предоставить все свойства, которые являются подтипами V (так что PickByValue<T, unknown> должно быть T ), тогда вы можете определить PickByValue следующим образом:

 type PickByValue<T, V> = Pick<T, { [K in keyof T]: T[K] extends V ? K : never }[keyof T]>
type TestA = PickByValue<Test, 'a'>; // {includeMe: "a"; andMe: "a"}
type IncludedKeys = keyof PickByValue<Test, 'a'>; // "includeMe" | "andMe"
  

Но если все, что вам нужно, это IncludedKeys , то вы можете сделать это более непосредственно с помощью KeysMatching<T, V> :

 type KeysMatching<T, V> = {[K in keyof T]: T[K] extends V ? K : never}[keyof T];
type IncludedKeysDirect = KeysMatching<Test, 'a'> // "includeMe" | "andMe"
  

Игровая площадка ссылка на код

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

1. Поразмыслив над этим, я понял, KeysMatching что это немного более гибко для моего конкретного варианта использования. Я приблизился к своим первоначальным попыткам, но не совсем добился успеха. Большое спасибо!

2. очень хороший ответ, type IntermediateType { includeMe: includeMe", andMe: "andMe, butNotMe: never, orMe: never } который type Result = IntermediateType[string] выдает "includeMe" | "andMe" | never | never , но never удален, поэтому это приводит к "includeMe" | "andMe"