使用
TypeScript
可以帮助咱们使用不少面向对象的特性和类型系统。可是从JavaScript
迁移到TypeScript
也须要巨大的时间和精力去完成重构。可是VS Code
中基于TypeScript
提供了对于JSDoc
的支持,咱们能够利用JSDoc
来给咱们的JavaScript
代码增长注释,加强代码的可读性和可维护性。javascript
首先咱们来看一下官网上的介绍:php
JSDoc 3 is an API documentation generator for JavaScript, similar to Javadoc or phpDocumentor. You add documentation comments directly to your source code, right alongside the code itself. The JSDoc tool will scan your source code and generate an HTML documentation website for you.html
JSDoc ( JSDoc 的最新版本是JSDoc 3) 实际上是经过特定格式的注释来帮助咱们生成 JavaScript
API文档的工具。相似的工具还有 Javadoc
或 phpDocumentor
.java
JSDoc's purpose is to document the API of your JavaScript application or library. It is assumed that you will want to document things like modules, namespaces, classes, methods, method parameters, and so on.git
JSDoc
的提供的注释标记类型能够参考Block Tags, 可是到如今为止,TypeScript
只支持了部分标记。
在语法方面,JSDoc
主要借鉴于 closure-compiler, 而 TypeScript
则有本身的一套类型语法,所以存在部分的差别。这里只介绍在 VS Code
中基于 TypeScript
的 JSDoc
用法。github
可以在 TypeScript
中使用的类型有:web
// 定义数组类型的三种方式
/** * 定义字符串数组类型 * @type {Array<string>} */
var strArr = ['1', '2'];
// 如下是另外两种方式,做用和第一种同样
/** * @type {Array.<string>} */
/** * @type {string[]} */
/** * 定义boolean类型 * @type {boolean} */
var isSelected = false;
/** * 定义string类型 * @type {string} */
var name = 'xyz';
复制代码
TypeScript
中添加的类型,好比:/** * 这是TypeScript定义的Navigator类型 * @type {Navigator} */
var navigator;
/** * 这是TypeScript定义的窗口类型 * @type {Window} */
var win;
/** * 这是TypeScript定义的HTML元素类型 * @type {HTMLElement} */
var rootElement = document.getElementById('root');
复制代码
/** * 定义了一个Animal类型,具备名称、年龄两个属性 * @type {{ name: string, age: number }} */
var cat = { name: 'miao', age: 2 };
复制代码
// 这是一个字符串类型/布尔类型
/** * 用来描述一个多是string或boolean的类型 * @type {(string | boolean)} */
var stringOrBoolean = '';
stringOrBoolean = false;
复制代码
/** * 用闭包的形式来定义函数类型 * @type {function(string, boolean): number} */
var function1;
/** * 用TypeScript的语法来定义函数类型 * @type {(s: string, b: boolean) => number} */
var function2;
/** * 使用内置的Function类型,不指定参数和返回值 * @type {Function} */
var function 3; 复制代码
/** * @typedef {object} Animal - 这是自定义的Animal类型 * @property {string} name 复杂类型的一个string类型属性 * @property {number} age 复杂类型的一个number类型属性 * @prop {boolean} [hasOwner] 复杂类型的一个boolean类型属性,可选 * @property {string[]=} toys 复杂类型的一个string数组属性,可选 * @prop {string} [ownerName='xyz'] 复杂类型的一个string类型属性,默认值为xyz, 可选 * */
/** * @type {Animal} */
var animal = { name: 'miao', age: 2, hasOwner: false }
复制代码
@callback相似于@typedef,区别在于: @typedef定义的是对象类型,包括函数类型,而@callback定义的是函数类型。typescript
/** * @callback Predicate * @param {string} data * @param {number} [index] * @returns {boolean} */
/** @type {Predicate} */
const ok = s => !(s.length % 2);
复制代码
/** * @param {string} name - string类型参数 * @param {string=} age - 可选参数,number类型 * @param {number} [hasOwner] - 可选参数,number类型 * @param {string} [ownerName="xyz"] - 带默认值的可选参数 * @return {string} 这是返回值 */
function getAnimal(name, age, hasOwner, ownerName){
// TODO
}
复制代码
枚举是一种在不少种语言中常见,可是在JavaScript中没有原生支持的数据类型。可是最让人残念的是,enum
竟然仍是保留的关键字——只是一直没有实现。 TypeScript是支持enum的,JSDoc也基于@enum提供了对枚举的支持:数组
/** * 文件类型 * @enum * @property {string} FileType.Image 图片 * @property {string} FileType.Video 视频 * @property {string} FileType.Audio 音频 * @property {string} FileType.Accessory 附件 */
export const FileType = {
/** 图片 */
Image: '1',
/** 视频 */
Video: '2',
/** 音频 */
Audio: '3',
/** 附件 */
Accessory: '4'
}
复制代码
@class/@constructor能够用来定义构造函数,而且只容许经过 new
关键字来调用构造函数。闭包
/** * @constructor * @param {number} width 宽度 * @param {number} height 高度 */
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype.getArea = function() {
return this.width * this.height
}
// 必需要经过new来调用,否则编辑器会报错
var rectrangele = new Rectangle();
复制代码
VS Code能够帮咱们作一些类型推断。可是有一些场景无法很好的作出推断,经过使用@this能够帮助咱们来显式指定 this
的类型。
/**
* @this {HTMLElement}
*/
function getScrollbarWidth() {
return this.offsetWidth - this.scrollWidth
}
复制代码
JSDoc中关于@type有 Nullable Type
和 Non-nullable Type
的概念,可是在TypeScript中只容许根据 strictNullChecks
标记类型为是否能够为null,并不能经过显示标注 non-nullablity
来实现和JSDoc的一致,例如:
/** * 在JSDoc中标记为可能为number或null类型 * @type {?number} */
/** * 在JSDoc中标记为number类型,而且不可能为null类型 * @type {!number} */
/** * 以上两种写法,在TypeScript下都等价于以下 * @type {number} */
复制代码
这是在TypeScript中独有的,JSDoc并不支持
// a.js
/** * @typedef Pet * @property name {string} */
/** * @type {Pet} */
var cat = { name: 'a' };
module.exports = {
// cat
};
// b.js
/** * @param p {import('./a').Pet} */
function walk(p) {
console.log(`${p.name} is walking!`)
}
// 也能够给引入的类型起别名
/** * @typedef { import('./a').Pet } MyPet */
/** * @type {MyPet} */
var mimi = { name: 'mimi' }
复制代码
这是JSDoc文档中没有说起的一种定义类型,只在google closure compiler中有说起,可是VS Code中有对应的支持:
/** * @param {T} x * @param {S} y * @template {number|string} T * @template {number|string} S */
function foo(x,y) { x=y; }
复制代码
这几项用的都很少,咱们能够看看官方文档的一些示例:
/** * @template T * @extends {Set<T>} */
class SortableSet extends Set {
// ...
}
复制代码
须要注意的是@extends/@augments只能用来定义基类的泛型参数,不能用来描述类的继承关系:
class Animal() {
run() {
}
}
/** * @extends {Animal} */
class Cat { }
var cat = new Cat()
// 这里会没有代码提示
cat.run()
复制代码