Proxy & Reflect
- 概念
- Proxy
- es6新增的一个对象拦截器,类似es5的defineProperty。
- 可以监听到一个对象的变化,取值和设置值,vue3也是通过proxy做的属性的劫持
- Reflect
- 配合Proxy用来操作对象
- Proxy
- 例子
type Person1 = { name: string age: number sex: string } const proxy = (obj: any, key: any) => { return new Proxy(obj, { get(target, prop, receiver) { console.log('get', prop) return Reflect.get(target, prop, receiver) }, set(target, prop, value, receiver) { console.log('set', prop) return Reflect.set(target, prop, value, receiver) }, }) } // 固定的太死了 const log1 = (obj: Person1, key: 'name' | 'age' | 'sex') => { return proxy(obj, key) } let ps1: Person1 = log1( { name: '亚索', age: 18, sex: '男', }, 'name' ) ps1.name = '瑞雯' ps1.sex console.log(ps1) // 优化后 const log2 = <T>(obj: T, key: keyof T): T => { return proxy(obj, key) } let ps2 = log2( { name: '盲僧', age: 20, sex: '男', like: 'hs', }, 'like' ) ps2.like
Partial & Pick
- 内置高级类型Partial Pick
- Partial
type Person1 = { name: string; age: number; msg: string; }; type p = Partial<Person1>;
- 源码
type Partial<T> = { [P in keyof T]?: T[P] }
- keyof 什么意思
- keyof 之后所有的key 都会变成这样 类似 for in
- type key = 'name' | 'age' | 'msg';
- Pick
- 选取指定一组属性,返回一个新的类型定义
type Person1 = { name: string; age: number; msg: string; }; type p = Pick<Person, 'name'>
- 源码
type Pick<T, K extends keyof T> = { [P in K]: T[P] }
- K extends keyof T 什么意思呢
- K 我们这传了个联合类型 通过 extends约束了下 你只能传你的约束的那些值 type key = 'name' | 'age' | 'msg'
type p = Pick<Person, 'xxxx'> // error
Record & Readonly
- Readonly
- 类似 Partial
- 例子
type Person1 = { name: string age: number msg: string } type p1 = Readonly<Person1> // p1 会变成这样 // type p1 = { // readonly name: string; // readonly age: number; // readonly msg: string; // }
- 源码
- 也是通过 keyof 把key变成联合类型 type key = 'name' | 'age' | 'msg';
- 然后通过in 遍历 给每个key 前面添加 readonly
- Record
- 例子
- 用来约束key,有两个参数
type Person1 = { name: string age: number msg: string } type K = 'A' | 'B' | 'C' type p1 = Record<K, Person1> // 使用 let obj3: p1 = { A: { name: '亚索', age: 18, msg: '嘻嘻' }, B: { name: '亚索', age: 18, msg: '嘻嘻' }, C: { name: '亚索', age: 18, msg: '嘻嘻' }, }
- 源码
type Record<K extends keyof any, T> = { [P in K]: T }
// keyof any 什么意思? type key = string | number | symbol
- 例子
infer
- 基础用法
- 新增的关键字充当占位符
- 例子
- 需求:定义一个类型 如果是数组类型 就返回 数组元素的类型 否则 就传入什么类型 就返回什么类型
- 以前可能会这么写
type Type<T> = T extends Array<any> ? T[number] : T type T1 = Type<(number | string)[]> type T2 = Type<boolean>
- 使用infer
type Type<T> = T extends Array<infer U> ? U : T type T1 = Type<(number | string)[]> type T2 = Type<boolean>
- 也可以约束成 never
// 只能传联合类型 不满足 就返回 never type Type<T> = T extends Array<infer U> ? U : never type T1 = [string, number] // [string, number] type T2 = Type<boolean> // never
- 类型提取
- 提取头部元素
type First<T extends any[]> = T extends [infer one, ...any[]] ? one : [] type T1 = First<Arrs> // type a = "a"
- 提取尾部元素
type Last<T extends any[]> = T extends [...any[], infer Last] ? Last : [] type T2 = Last<Arrs> // type b = "c"
- 删除头部元素
type Shift<T extends any[]> = T extends [unknown, ...infer Rest] ? Rest : [] type T3 = Shift<Arrs> // type T3 = type T3 = ["b", "c"]
- 删除尾部元素
type Pop<T extends any[]> = T extends [...infer Rest, unknown] ? Rest : [] type T4 = Pop<Arrs> // type T4 = ["a", "b"]
- 提取头部元素
- 递归
- 需求
// 需求 Arr1 正常排序 变成 Arr2 那样 type Arr1 = [6, 5, 4, 3, 2, 1] type Arr2 = [1, 2, 3, 4, 5, 6]
- 思路
- 使用泛型约束 只能传数组类型
- 然后提取第一个放入末尾, 循环操作 形成递归 满足条件 返回
- 例子
type ReveArr<T extends any[]> = T extends [infer First, ...infer rest] ? [...ReveArr<rest>, First] : T type Result = ReveArr<Arr1> // type Result = [1, 2, 3, 4, 5, 6]
- 需求