前言
-
本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
-
这是源码共读的第2期,链接:juejin.cn/post/708499… 。
学习目标
- 学习ts在工具函数中的使用场景、作用及意义
util工具函数知识点
emptyObject中学Record
不可增、删、改的空对象及其原型,但是当对象嵌套过深还是能修改的
export const emptyObject: Record<string, any> = Object.freeze({})
/**
* Record<string, any>:
* 关于Record不得不说的故事
* Record的来历:
* Record是ts的内置类型,泛型类型
* type Record<K extends keyof any, T> = {
* [P in K]: T
* }
* 定义了一个emptyObject变量,允许key为string类型,value为任意类型
*/
isUndef中is的使用
export function isUndef(v: any): v is undefined | null {
return v === undefined || v === null
}
/**
* v is undefined | null 如何理解呢?
* 是ts中的类型谓词语法(type predicate):表示一个类型断言的结果
* 语法形式: parameterName is Type
* 解释: parameterName:参数名 Type是ts类型
* v is undefined | null 理解为v是否属于undefined | null ,即返回的结果是一个Boolean类型
* 作用:用于表示类型缩小操作,帮助ts编译器更准确推断变量类型,提高代码安全性
*/
isFunction中学习函数类型定义
export function isFunction(value: any): value is (...args: any[]) => any {
return typeof value === 'function'
}
/**
* value is (...args: any[]) => any 如何理解?
* 表示断言value是函数类型,约束了value的类型范围
* 函数返回值是一个Boolean类型,表示参数value是否属于(...args: any[]) => any 类型
* (...args: any[]) => any 作为一个整体去理解,是一个函数类型,表示具有任意参数和任意返回值的函数类型
* 可以将参数value的类型缩小为函数类型,入参中限制参数必须为函数类型
* is这里还是用到了类型谓词语法,参照上述的isUndef
* value is (...args: any[]) => any通过is类型断言为Boolean类型,fucntion中return typeof value === 'function'也是返回Boolean类型,形成一致约束
*
*/
isRegExp中学习ts类型分类
export function isRegExp(v: any): v is RegExp {
return _toString.call(v) === '[object RegExp]'
}
/**
* v is RegExp 也是类型谓词语法形式,返回布尔类型,断言v是RegExp(正则)类型
* 除此之外,延申一点:
* ts中的类型可以分为以下几类:
* 基本类型:string、number、boolean、null、undefined、symbol等都js的基本类型
* 对象类型:Object、Date、RegExp、Array、class、tuple、enum等
* 函数类型:普通函数类型、箭头函数类型、构造函数类型
* 泛型:泛型函数类型、泛型类类型
* 高级类型:交叉类型、联合类类型、类型别名、类型推断、类型守卫
* 其他类型:void、never、unkown、any等
*
*/
isPromise中学Promise类型定义
export function isPromise(val: any): val is Promise<any> {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}
/**
* promise在ts类型定义中表示 interface Promise<T>{}
* <T>表示泛型参数
* 根据上述中对ts类型的总结可知 Promise<any>是一个泛型类型
* Promise<any>表示返回值为任意类型的Promise对象
*/
extend中学习PropertyKey
export function extend(
to: Record<PropertyKey, any>,
_from?: Record<PropertyKey, any>
): Record<PropertyKey, any> {
for (const key in _from) {
to[key] = _from[key]
}
return to
}
/**
* PropertyKey:ts内置类型
* type PropertKey = string | number | symbol
* 作用:对于对象类型的key,用来约束其类型
*
* 使用场景:
* 1.定义对象的属性名或方法名的类型
* 2.定义函数的参数类型
*
* Record<PropertyKey, any>
* 语法:Record<Keys, Values>
* Keys 表示属性名的类型 Values 表示属性值的类型
* 理解:约束了对象的属性名为number、string、symbol类型,属性值可以是任何类型
*/
looseIndexOf中学习unknown使用场景
export function looseIndexOf(arr: Array<unknown>, val: unknown): number {
for (let i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) return i
}
return -1
}
/**
* ts中什么情况下需要使用unknown而不是any表示参数类型定义?
* 关于unknown和any不得不区分的使用场景?
* unknown:变量的类型是未知的,需要进行类型检查或类型转换才能安全使用
* any:任何类型都可以赋值给变量
* 使用场景(使用unknown而不是any):
* 1.当函数参数类型未知时:参数类型未知,在函数内部对参数进行类型检查或类型转换操作,可用unknown表示
* 2.当使用第三方库或接口时:这时候可能第三方库或接口返回的信息不完整或不准确就用unknown去定义,并在函数内部进行类型检查或类型转换
* any类型的使用会导致ts提供的类型检查和类型推断功能不执行
* 故实际开发中优先使用更具体的类型来表示变量的类型
*/
once学习类型拆解
export function once<T extends (...args: any[]) => any>(fn: T): T {
let called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments as any)
}
} as any
}
/**
* function once<T extends (...args: any[]) => any>(fn: T): T {}
* ts类型拆解:
* 1.泛型函数
* function once<T>(fn:T): T{}
* 2.对声明的泛型类型T的约束
* T extends (...args: any[]) => any :表示T约束为一个函数类型
* (...args: any[]) => any 表示一个参数是任意,返回值任意的泛型函数类型
* extends表示继承,约束,约束T为一个函数类型
*
*/
hasChanged中学习as使用
export function hasChanged(x: unknown, y: unknown): boolean {
if (x === y) {
// 为了处理x,y都是0或-0的边缘情况
return x === 0 && 1 / x !== 1 / (y as number) // y as number 将y强制转化为number类型
} else {
return x === x || y === y // 为了处理x或y都是NaN(不是数字的情况)
}
}
/**
* as
* 定义语法: value as Type
* value:要进行类型转换的值,Type表示要转换成的类型
*
* 使用as的条件:
* 1.要转换的值和目标类型必须兼容,即要转换的值必须包含目标类型的所有属性和方法,或者可以通过一些方法进行转换
* 2.转换后的值的类型必须能够被ts推导出来,并且与目标类型相同或兼容
*
* 常用场景:
* 1.将一种类型转为另一种类型
* 2.将泛型类型转化为具体类型
* 3.将断言类型转换为具体类型
*
*/
总结
通过对ts版本工具函数的学习,了解到了ts在实际开发场景中的实践,其中对Record
、is
、as
、(...args: any[]) => any
、ts类型分类
、unknown与any
、PropertyKey
、Promise类型定义
、复杂ts拆解分析
等有有了新的认识,也为自己在项目开发中如何使用ts提供了新的思路,从现在开始也尝试在自己项目中使用起来,上述所有见解都属于个人看法,有什么错误欢迎大家来指正!
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END