Как отфильтровать родительский тип, чтобы выбрать детей данного типа в TypeScript? - PullRequest
1 голос
/ 13 октября 2019

Что мне нужно

У меня есть неопределенное количество объектов в родительском объекте со значением ключа. У каждого дочернего элемента есть свойство namespaced типа boolean:

const obj1 = {
  namespaced: true,
  a() {}
} as const

const obj2 = {
  namespaced: false,
  b() {}
} as const

const parentObj = {
  obj1,
  obj2
} as const

Возможно ли создать сопоставленный тип, который содержит только объекты с namespaced, установленным на true (и то же самое с false)?

То, что я пытался

interface ParentObj {
  [name: string]: Obj
}

interface Obj {
  namespaced: boolean
}

type FilterNamespaced<P extends ParentObj> = {
  [O in keyof P]: P[O] extends { namespaced: true } ? P[O] : never
}

type FilterNotNamespaced<P extends ParentObj> = {
  [O in keyof P]: P[O] extends { namespaced: false } ? P[O] : never
}

type F1 = FilterNamespaced<typeof parentObj>

type F2 = FilterNotNamespaced<typeof parentObj>

Это почти сделано, но F1 по-прежнему содержит ключ obj2 типа никогда, а F2 содержит ключ obj1 слишком. Я хотел бы иметь то же самое, но без этих ключей.

1 Ответ

1 голос
/ 13 октября 2019

Вы можете сделать это, но вам нужен дополнительный уровень косвенности. Вам необходимо сначала отфильтровать ключи, а затем выбрать их из исходного типа. Используя что-то вроде KeyOfType из здесь , вы попадете туда, куда хотите:


type KeyOfType<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T]

type FilterNamespaced<P extends ParentObj> = Pick<P, KeyOfType<P, { namespaced: true }>>

type FilterNotNamespaced<P extends ParentObj> = Pick<P, KeyOfType<P, { namespaced: false }>>

Play

...