[Typescript] 24. Medium - Type Lookup
Sometimes, you may want to lookup for a type in a union to by their attributes.
In this challenge, we would like to get the corresponding type by searching for the common type
field in the union Cat | Dog
. In other words, we will expect to get Dog
for LookUp<Dog | Cat, 'dog'>
and Cat
for LookUp<Dog | Cat, 'cat'>
in the following example.
interface Cat {
type: 'cat'
breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}
interface Dog {
type: 'dog'
breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
color: 'brown' | 'white' | 'black'
}
type MyDogType = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`
interface Cat {
type: 'cat'
breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}
type x = Cat extends {type: 'cat'} ? true: false // true
/* _____________ Your Code Here _____________ */
type LookUp<T extends {type: string}, Kind extends string> = T extends {type: Kind} ? T: never;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
interface Cat {
type: 'cat'
breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}
interface Dog {
type: 'dog'
breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
color: 'brown' | 'white' | 'black'
}
type Animal = Cat | Dog
type cases = [
Expect<Equal<LookUp<Animal, 'dog'>, Dog>>,
Expect<Equal<LookUp<Animal, 'cat'>, Cat>>,
]
---
One step further:
type LookUp<U extends {[Key in K]: string}, T extends string, K extends string = 'type'> = U extends {[Key in K]: T} ? U : never
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
interface Cat {
kind: 'cat'
breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}
interface Dog {
kind: 'dog'
breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
color: 'brown' | 'white' | 'black'
}
type Animal = Cat | Dog
type cases = [
Expect<Equal<LookUp<Animal, 'dog', 'kind'>, Dog>>,
Expect<Equal<LookUp<Animal, 'cat', 'kind'>, Cat>>,
]
---
One step further;
type LookUpKey<U extends {[Key in K]: string}, T extends string, K extends string = 'type'> = U extends {[Key in K]: T} ? U : never;
type LookUpLike<U extends Record<PropertyKey, any>, T extends Record<PropertyKey, any>> = U extends T ? U : never;
type LookUp<
U extends Record<PropertyKey, any>,
T extends Record<PropertyKey, any> | string,
K extends string = 'type'
> = T extends Record<PropertyKey, any>
? LookUpLike<U, T>
: T extends string
? LookUpKey<U, T, K>
: never;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
interface Cat {
kind: 'cat'
breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}
interface Dog {
kind: 'dog'
breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
color: 'brown' | 'white' | 'black'
}
type Animal = Cat | Dog
type cases = [
Expect<Equal<LookUp<Animal, 'dog', 'kind'>, Dog>>,
Expect<Equal<LookUp<Animal, 'cat', 'kind'>, Cat>>,
Expect<Equal<LookUp<Animal, {kind: 'dog'}>, Dog>>,
Expect<Equal<LookUp<Animal, {kind: 'cat'}>, Cat>>,
]