TypeScript 的注释指令
TypeScript 接受一些注释指令。
所谓“注释指令”,指的是采用 JS 双斜杠注释的形式,向编译器发出的命令。
// @ts-nocheck
// @ts-nocheck
告诉编译器不对当前脚本进行类型检查,可以用于 TypeScript 脚本,也可以用于 JavaScript 脚本。
// @ts-nocheck
const element = document.getElementById(123);
上面示例中,document.getElementById(123)
存在类型错误,但是编译器不对该脚本进行类型检查,所以不会报错。
// @ts-check
如果一个 JavaScript 脚本顶部添加了// @ts-check
,那么编译器将对该脚本进行类型检查,不论是否启用了checkJs
编译选项。
// @ts-check
let isChecked = true;
console.log(isChceked); // 报错
上面示例是一个 JavaScript 脚本,// @ts-check
告诉 TypeScript 编译器对其进行类型检查,所以最后一行会报错,提示拼写错误。
// @ts-ignore
// @ts-ignore
告诉编译器不对下一行代码进行类型检查,可以用于 TypeScript 脚本,也可以用于 JavaScript 脚本。
let x:number;
x = 0;
// @ts-ignore
x = false; // 不报错
上面示例中,最后一行是类型错误,变量x
的类型是number
,不能等于布尔值。但是因为前面加上了// @ts-ignore
,编译器会跳过这一行的类型检查,所以不会报错。
// @ts-expect-error
// @ts-expect-error
主要用在测试用例,当下一行有类型错误时,它会压制 TypeScript 的报错信息(即不显示报错信息),把错误留给代码自己处理。
function doStuff(abc: string, xyz: string) {
assert(typeof abc === "string");
assert(typeof xyz === "string");
// do some stuff
}
expect(() => {
// @ts-expect-error
doStuff(123, 456);
}).toThrow();
上面示例是一个测试用例,倒数第二行的doStuff(123, 456)
的参数类型与定义不一致,TypeScript 引擎会报错。但是,测试用例本身测试的就是这个错误,已经有专门的处理代码,所以这里可以使用// @ts-expect-error
,不显示引擎的报错信息。
如果下一行没有类型错误,// @ts-expect-error
则会显示一行提示。
// @ts-expect-error
console.log(1 + 1);
// 输出 Unused '@ts-expect-error' directive.
上面示例中,第二行是正确代码,这时系统会给出一个提示,表示@ts-expect-error
没有用到。
JSDoc
TypeScript 直接处理 JS 文件时,如果无法推断出类型,会使用 JS 脚本里面的 JSDoc 注释。
使用 JSDoc 时,有两个基本要求。
(1)JSDoc 注释必须以/**
开始,其中星号(*
)的数量必须为两个。若使用其他形式的多行注释,则 JSDoc 会忽略该条注释。
(2)JSDoc 注释必须与它描述的代码处于相邻的位置,并且注释在上,代码在下。
下面是 JSDoc 的一个简单例子。
/**
* @param {string} somebody
*/
function sayHello(somebody) {
console.log('Hello ' + somebody);
}
上面示例中,注释里面的@param
是一个 JSDoc 声明,表示下面的函数sayHello()
的参数somebody
类型为string
。
TypeScript 编译器支持大部分的 JSDoc 声明,下面介绍其中的一些。
@typedef
@typedef
命令创建自定义类型,等同于 TypeScript 里面的类型别名。
/**
* @typedef {(number | string)} NumberLike
*/
上面示例中,定义了一个名为NumberLike
的新类型,它是由number
和string
构成的联合类型,等同于 TypeScript 的如下语句。
type NumberLike = string | number;
@type
@type
命令定义变量的类型。
/**
* @type {string}
*/
let a;
上面示例中,@type
定义了变量a
的类型为string
。
在@type
命令中可以使用由@typedef
命令创建的类型。
/**
* @typedef {(number | string)} NumberLike
*/
/**
* @type {NumberLike}
*/
let a = 0;
在@type
命令中允许使用 TypeScript 类型及其语法。
/**@type {true | false} */
let a;
/** @type {number[]} */
let b;
/** @type {Array<number>} */
let c;
/** @type {{ readonly x: number, y?: string }} */
let d;
/** @type {(s: string, b: boolean) => number} */
let e;
@param
@param
命令用于定义函数参数的类型。
/**
* @param {string} x
*/
function foo(x) {}
如果是可选参数,需要将参数名放在方括号[]
里面。
/**
* @param {string} [x]
*/
function foo(x) {}
方括号里面,还可以指定参数默认值。
/**
* @param {string} [x="bar"]
*/
function foo(x) {}
上面示例中,参数x
的默认值是字符串bar
。
@return,@returns
@return
和@returns
命令的作用相同,指定函数返回值的类型。
/**
* @return {boolean}
*/
function foo() {
return true;
}
/**
* @returns {number}
*/
function bar() {
return 0;
}
@extends 和类型修饰符
@extends
命令用于定义继承的基类。
/**
* @extends {Base}
*/
class Derived extends Base {
}
@public
、@protected
、@private
分别指定类的公开成员、保护成员和私有成员。
@readonly
指定只读成员。
class Base {
/**
* @public
* @readonly
*/
x = 0;
/**
* @protected
*/
y = 0;
}