/*
  62 - Type Lookup
  -------
  by Anthony Fu (@antfu) #medium #union #map
  
  ### Question
  
  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.
  
  ```ts
  interface Cat {
    type: 'cat'
    breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
  }
  
  interface Dog {
    type: 'dog'
    breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
    color: 'brown' | 'white' | 'black'
  }
  
  const MyDog = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`

View on GitHub: https://tsch.js.org/62 */

/* _____________ Your Code Here _____________ */

type LookUp<U, T> = any

/* _____________ Test Cases _____________ */ import { 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>>, ]

/* _____________ Further Steps _____________ / /

Share your solutions: https://tsch.js.org/62/answer View solutions: https://tsch.js.org/62/solutions More Challenges: https://tsch.js.org */


타입을 추론할 수 있도록 돕는 것이 관건 인 것 같다.

놀라운 솔루션을 참고했다.

```tsx
type LookUp<U, T> = U extends {type: T} ? U : never;

정리

U 의 조건문으로 { type: T } 인 경우 U 를 리턴하게 했다. 이 과정을 통해서 똑똑한 컴파일러가 타입을 추론하게 된다. 만약 서로 일치하지 않는 다면 never 를 리턴한다. 아주 합리적이다.

T'dog' 이면 조건문 에서 type: 'dog' 이 되니깐 U 를 리턴할 때 type: 'dog' 프로퍼티를 가진 객체를 리턴하는 것이다!

좀더 스트릭하게 쓸 수 있도록 바꿔 보았다.

type LookUp<U extends { type: string }, T extends U['type']> = U extends { type: T } ? U : never