体操

78 阅读2分钟

hello world

type HelloWorld = any

/* _____________ Test Cases _____________ */
import type { Equal, Expect, NotAny } from '@type-challenges/utils'

type cases = [
  Expect<NotAny<HelloWorld>>,
  Expect<Equal<HelloWorld, string>>,
]
答案
type HelloWorld = string

实现 TS 内置的 Pick<T, K>,从类型 T 中选择出属性 K,构造成一个新的类型

type MyPick<T, K> = any

/* _____________ 测试用例 _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
  Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
  // @ts-expect-error
  MyPick<Todo, 'title' | 'completed' | 'invalid'>,
]

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
}

interface Expected2 {
  title: string
  completed: boolean
}
答案:
type MyPick<T, K extends keyof T> = {
  [key in K] : T[key]
}
注:
keyof: 取interface的键后保存为联合类型
interface userInfo {
    name: string
    age: number
}
type keyofValue = keyof userInfo
// keyofValue = "name" | "age"

in: 取联合类型的值,主要用于数组和对象的构建
type name = 'firstname' | 'lastname'
type TName = {
  [key in name]: string
}
// TName = { firstname: string, lastname: string }

实现内置的Readonly<T>,接收一个 泛型参数,并返回一个完全一样的类型,所有属性都会被 readonly 所修饰

    type MyReadonly<T> = {
        [key in keyof T] : Readonly keyof T[key]
    }

    import type { Equal, Expect } from '@type-challenges/utils'

    type cases = [
        Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>,
    ]

    interface Todo1 {
        title: string
        description: string
        completed: boolean
        meta: {
            author: string
        }
    }
答案:
type MyReadonly<T> = {
  readonly [key in keyof T] : T[key]
}

传入一个元组类型,将这个元组类型转换为对象类型,这个对象类型的键/值都是从元组中遍历出来

type TupleToObject<T extends readonly any[]> = any

/* _____________ 测试用例 _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
const tupleNumber = [1, 2, 3, 4] as const
const tupleMix = [1, '2', 3, '4'] as const

type cases = [
  Expect<Equal<TupleToObject<typeof tuple>, { tesla: 'tesla'; 'model 3': 'model 3'; 'model X': 'model X'; 'model Y': 'model Y' }>>,
  Expect<Equal<TupleToObject<typeof tupleNumber>, { 1: 1; 2: 2; 3: 3; 4: 4 }>>,
  Expect<Equal<TupleToObject<typeof tupleMix>, { 1: 1; '2': '2'; 3: 3; '4': '4' }>>,
]

// @ts-expect-error
type error = TupleToObject<[[1, 2], {}]>

答案:
type TupleToObject<T extends readonly PropertyKey[]> = {
  [P in T[number]] : P
}

如何遍历元祖中的每一项:可以通过number索引,也就是T[number]获取到每一项。  
T extends readonly PropertyKey[]:要传入的是一个可作为键类型的数组,而T[]这种是不合法的,所以需要使用extends去构造一个新的类型。