TypeScript 杂记二 《类型体操》

TypeScript 杂记二 《类型体操》

type-challenges 题目

前提

type A = keyof any
// ===
type A = string | number | symbol

// infer 表示待推断的类型,如下内置类型
type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any
type B = ReturnType<(value: string) => string>
// ===
type B = string

type Func = () => void
type C = keyof Func
// ===
type C = never

class Class {}
type C = keyof Class
// ===
type C = never

Pick<T, K>

type _Pick<T, K extends keyof T> = {
  [P in K]: T[P]
}

Readonly

type _Readonly<T> = {
  readonly [P in keyof T]: T[P]
}

Partial

type _Partial<T> = {
  [P in keyof T]?: T[P]
}

Required

type _Required<T> = {
  [P in keyof T]-?: T[P]
}

Record<T, K>

type _Record<T extends keyof any, K> = {
  [P in T]: K
}

Exclude<T, K>

type _Exclude<T, K> = T extends K ? never : T

Extract<T, K>

type _Extract<T, K> = T extends K ? T : never

Omit<T, K>

type _Omit<T, K extends keyof any> = _Pick<T, _Exclude<keyof T, K>>

First

实现一个通用 First<T>,它接受一个数组 T 并返回它的第一个元素的类型

type First<T extends any[]> = T extends [] ? never : T[0]

Last

实现一个通用 Last<T>,它接受一个数组 T 并返回它的最后一个元素的类型

type First<T extends any[]> = T extends [...infer O, infer R] ? R : never

Readonly2<T, K>

实现一个通用的 Readonly2<T, K>,K 指定应设置为 Readonly 的 T 的属性集。如果未提供 K,则应使所有属性都变为只读,就像普通的 Readonly一样

// 自己写的
type Readonly2<T, K extends keyof T = any> = K extends never
  ? Readonly<T>
  : {
      readonly [P in K]: T[P]
    } & {
      [P in Exclude<keyof T, K>]: T[P]
    }

// 别人的精简版
type Readonly2<T, K extends keyof T = keyof T> = {
  readonly [P in K]: T[P]
} & Omit<T, K>

DeepReadonly

实现一个通用的 DeepReadonly<T>,它将对象的每个参数及其子对象递归地设为只读

// 满足简单数据结构
type DeepReadonly<T> = {
  readonly [P in keyof T]: DeepReadonly<T[P]>
}
// 处理函数和类,原因查看前提的内容
type DeepReadonly<T> = keyof T extends never
  ? T
  : {
      readonly [P in keyof T]: DeepReadonly<T[P]>
    }

Trim

type trimed = Trim<' Hello World '> // expected to be 'Hello World'

// 处理左侧的空格和换行,infer 请查看前提
// 一个一个递归处理
type TrimL<T extends string> = T extends `${' ' | '\t' | '\n'}${infer S}`
  ? TrimL<S>
  : T
// 同理处理右侧
type TrimR<T extends string> = T extends `${infer S}${' ' | '\t' | '\n'}`
  ? TrimR<S>
  : T
type Trim<T extends string> = TrimL<TrimR<T>>

// 整合起来
type Trim<T extends string> = T extends `${' ' | '\t' | '\n'}${infer L}`
  ? Trim<L>
  : T extends `${infer R}${' ' | '\t' | '\n'}`
  ? Trim<R>
  : T

vue

实现类似 Vue 的类型支持的简化版本

const instance = SimpleVue({
  data() {
    return {
      firstname: 'Type',
      lastname: 'Challenges',
      amount: 10,
    }
  },
  computed: {
    fullname() {
      return this.firstname + ' ' + this.lastname
    },
  },
  methods: {
    hi() {
      alert(this.fullname.toLowerCase())
    },
  },
})
type ComputedReturn<T> = {
  [K in keyof T]: T[K] extends () => infer R ? R : never
}
declare function SimpleVue<D, C, M>(options: {
  data?(this: {}): D
  computed?: C & ThisType<D & ComputedReturn<C> & M>
  methods?: M & ThisType<D & ComputedReturn<C> & M>
}): D & ComputedReturn<C> & M
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值