[TypeScript] Type Challenges #62 - Type Lookup

29 阅读1分钟

题目描述

有时,您可能希望根据某个属性在联合类型中查找类型。

在此挑战中,我们想通过在联合类型Cat | Dog中通过指定公共属性type的值来获取相应的类型。换句话说,在以下示例中,LookUp<Dog | Cat, 'dog'>的结果应该是DogLookUp<Dog | Cat, 'cat'>的结果应该是Cat

interface Cat {
  type'cat'
  breeds'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}

interface Dog {
  type'dog'
  breeds'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
  color'brown' | 'white' | 'black'
}

type MyDog = LookUp<Cat | Dog'dog'// expected to be `Dog`

题解

// ============= Test Cases =============
import type { EqualExpect } from './test-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>>,
]


// ============= Your Code Here =============
type LookUp<U, T extends PropertyKey> = U extends { type: T } ? U : never

类型约束

使用T extends PropertyKey对类型T进行约束,确保T是合法的键类型

条件类型

  • U extends { type: T } ? U : never是一个条件类型,检查U是否满足{ type: T }
    • 如果U满足{ type: T },则返回U
    • 如果U不满足{ type: T },则返回never

分布式条件判断

U是一个联合类型时,TypeScript 会进行分布式条件判断 ,将条件应用到联合类型的每个成员上

例如:LookUp<Animal, 'dog'>会拆分成以下两个条件类型检查:

LookUp<Cat'dog'>
LookUp<Dog'dog'>
  • LookUp<Cat, 'dog'>Cat类型的type属性是'cat',不满足{ type: 'dog' },因此返回never
  • LookUp<Dog, 'dog'>Dog类型的type属性是'dog',满足{ type: 'dog' },因此返回Dog

由于never在联合类型中会被自动排除,所以LookUp<Animal, 'dog'>的最终结果是Dog