前言
当 TypeScript 越来越流行时,许多项目选择运用 TypeScript 进行开发,由于它带来了许多优点,这一点咱们都有所耳闻。
然而,一些旧项目依然采用传统的 JavaScript 技能,由于进行全面重构成本太高。
在这种情况下,咱们就需要介绍 JSDoc(也称为文档注释)作为一种解决方案。
JSDoc 是一种在 JavaScript 中运用注释来供给类型信息和文档阐明的办法。 JSDoc 不仅能够供给类型提示,还能够生成文档,协助开发人员更好地了解代码。
JSDoc 的出现为传统 JavaScript 项目引入了一种新的方式,使得即便在没有 TypeScript 的情况下,也能够获得一些相似 TypeScript 的优点。
重新看待JSDoc
信任咱们都曾见过下面这样的写法,经过运用 @param
标签符号函数参数的名称、类型和描绘,运用 @returns
标签符号函数回来值
/**
* 方针兼并,假如存在相同的特点,优先运用 target 的特点.
*/
function merge(source, target) { ... }
/**
* 方针兼并,假如存在相同的特点,优先运用 target 的特点.
* @param { Object } source 源方针
* @param { Object } target 方针方针
* @returns { Object } 回来兼并后的新方针
*/
function merge(source, target) { ... }
但假如是以下这样呢,是不是就有点TS的滋味了(手动狗头)
/**
* 方针兼并,假如存在相同的特点,优先运用 target 的特点
* @template { Record<string, any> } T
* @template { Record<string, any> } U
* @param { T } source 源方针
* @param { U } target 方针方针
* @returns { Omit<T, keyof (T | U)> & U } 回来兼并后的新方针
*/
function merge(source, target) { ... }
const test = merge({ name: 'test', gender: '男' }, { age: 18, gender: 1 })
能够在 JSDoc 中运用 TS 语法,这样的话,就算在 JS 开发的项目中,“体操哥”不也有发挥空间了嘛。
假定你现已具备了一定的TS水平,那接下来让咱们直接进入正题。假如你不太了解甚至为泛型而感到头疼,《TS类型的进阶运用 – 》这篇文章希望能够帮到你。
泛型
当谈到 TS 时,最具挑战性的部分莫过于泛型。泛型能够说是 TS 的精华,它为咱们供给了在编写灵敏且类型安全的代码时所需的强大东西。泛型使得咱们能够以一种抽象的方式来处理不同类型的数据,然后提高了代码的灵敏性和可维护性。
在 JSDoc 中运用 @template
标签声明泛型:
/**
* @template T 声明泛型
* @param { T } value 入参
* @returns { T } 回来值
*/
function identity(value) { } // function identity<T>(value: T): T
const a = identity("text"); // string
const b = identity(123); // number
能够从提示中看到 identity
现已变成了一个规范的泛型函数了,传入什么类型回来什么类型
运用逗号或多个标签声明多个泛型参数:
/**
* @template T,U,V
* @template W,X
*/
还能够在泛型名称之前进行泛型约束:
/**
* @template { unknown[] } T
* @param { T } value 要获取长度的数组
* @returns { T['length'] } 数组的长度
*/
能够看到这些满是数组的办法和特点,编辑器现已能够识别出你的 T
是一个数组了
最终,还能够为泛型设置默许类型:
/**
* @template [T = string] 声明泛型并设置默许类型为string
* @param { T } value 入参
* @returns { T } 回来值
*/
function identity(value = '') { }
omit函数
结合之前所讲的泛型,来看看一个经典的函数——omit
/**
* omit函数 去除方针中的值得特点
* @template { Record<string, any> } T 方针类型
* @template { Array<keyof T> } K 元组类型
* @param { T } target 方针元素
* @param { K } keys 特点
* @returns { Omit<T, K[number]> } 新方针
*/
function omit(target, keys) { ... }
作用:
总结:
- 能得到作用1,归功于
@template { Array<keyof T> } K 元组类型
这段代码将泛型K
的类型约束成(name | gender)[]
,使元组中的每个方位都是泛型T
方针类型上的特点。 - 作用2则归功于多个泛型参数以及泛型约束,
K[number]
将元组转成联合类型,假定函数的形参keys
为[name, gender]
那么将转换为name | gender
,所以图中的转换为[name]
=>name
;然后再结合Omit
即可达到咱们想要的作用了。能够拿到keys
具体的类型十分要害,想想假如只要一个泛型参数能够做到吗?
杂乱类型
在前面,咱们所评论的类型中,都是一些简略的类型,一行代码就能够搞定的,假如某个函数的类型特别杂乱,需要写许多代码,这时候又该怎么应对呢?
类型导入
运用 import
从其他文件中导入类型
// 文件:utils.d.ts
// 阐明:过滤掉方针中特点值为指定内容的特点,运用 as 要害字来进行过滤
export type RemovePropertiesByValue<T extends Record<string, any>, V extends readonly unknown[]> = {
[K in keyof T as T[K] extends V[number] ? never : K]: T[K]
}
// 文件:JSDoc.js
/**
* 去除方针中特点值为空的特点
* @template { Record<string, any> } T
* @template { readonly any[] } [V = [undefined, null]]
* @param { T } target 要处理的方针
* @param { V } values 自定义过滤的value值,默许为[undefined, null]
* @returns { import("./utils").RemovePropertiesByValue<T, V> } 处理后的方针
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*/
function filterObjectEmpty(target, values = [undefined, null]) { }
const test4 = filterObjectEmpty({ name: undefined, age: 18, gender: '', address: null }) // 测试代码
咱们从 utils.d.ts
类型文件中运用import
导入了 RemovePropertiesByValue
类型,此类型接收两个泛型参数。@returns { import("./utils").RemovePropertiesByValue<T, V> }
导入了此类型并将 泛型T 和 泛型V 作为参数传递给 RemovePropertiesByValue
既然如此,还有什么类型是无法用 JSDoc 处理的呢,我想只要咱们无法写的类型吧 本文的要点(泛型)现已讲完,假如你对 JSDoc 现已有了爱好,能够去具体看看官方文档