字符串
let firstname: string = 'Captain'; // 字符串字面量
let familyname: string = String('S'); // 显式类型转换
let fullname: string = `my name is ${firstname}.${familyname}`; // 模板字符串
说明:所有 JavaScript 支持的定义字符串的方法,我们都可以直接在 TypeScript 中使用。
数字
/** 十进制整数 */
let integer: number = 6;
/** 十进制整数 */
let integer2: number = Number(42);
/** 十进制浮点数 */
let decimal: number = 3.14;
/** 二进制整数 */
let binary: number = 0b1010;
/** 八进制整数 */
let octal: number = 0o744;
/** 十六进制整数 */
let hex: number = 0xf00d;
/** 大整数 */
let big: bigint = 100n;
请注意:虽然number和bigint都表示数字,但是这两个类型不兼容。
布尔
/** TypeScript 真香 为 真 */
let TypeScriptIsGreat: boolean = true;
/** TypeScript 太糟糕了 为 否 */
let TypeScriptIsBad: boolean = false;
Symbol
let sym1: symbol = Symbol();
let sym2: symbol = Symbol('42');
数组
/** 子元素是数字类型的数组 */
let arrayOfNumber: number[] = [1, 2, 3];
/** 子元素是字符串类型的数组 */
let arrayOfString: string[] = ['x', 'y', 'z'];
/** 子元素是数字类型的数组 */
let arrayOfNumber: Array<number> = [1, 2, 3];
/** 子元素是字符串类型的数组 */
let arrayOfString: Array<string> = ['x', 'y', 'z'];
元组
const x: [State, SetState] = [state, setState];
const y: [SetState, State] = [setState, state];
使得定义包含固定个数元素、每个元素类型未必相同的数组成为可能。元组相较对象而言,不仅为我们实现解构赋值提供了极大便利,还减少了不少代码量,这可能也是 React 官方如此设计核心 Hooks 的重要原因之一。
特殊类型 any
any 指的是一个任意类型,它是官方提供的一个选择性绕过静态类型检测的作弊方式。
any 类型会在对象的调用链中进行传导,即所有 any 类型的任意属性的类型都是 any,如下代码所示:
let anything: any = {};
let z = anything.x.y.z; // z 类型是 any,不会提示错误
z(); // 不会提示错误
TS 中的 any 指的是一个任意类型,它是官方提供的一个选择性绕过静态类型检测的作弊方式。
长远的角度来看,应该避免使用 any。如果在 TS 项目中,导出都是 any,那和直接书写 js 没什么区别,TS 也失去了意义。因此除非有特殊情况,不然应禁止使用 any 类型。
unknown
TS 3.0 新添加的一个类型,用于注解不不确定的变量类型。例如:
let result: unknown;
if (x) {
result = x();
} else if (y) {
result = y();
} ...
但是与 any 类型不同的是,unknown 类型更加安全,比如我们可以将任意类型的值赋值给 unknown,但是 unknown 只能赋值给 any 和 unknown 类型。使用 unknown 后,TS 会对它做类型校验,但是如果不缩小类型。对 unknown 执行的操作将会报错。
void 、undefined、null
可以把 undefined 值或类型是 undefined 的变量赋值给 void 类型变量,反过来,类型是 void 但值是 undefined 的变量不能赋值给 undefined 类型。
never
never 表示永远不会发生值的类型。
定义一个统一抛出错误的函数 ```javascript function ThrowError(msg: string): never {
throw Error(msg);
}
- 函数代码中是一个死循
```javascript
function InfiniteLoop(): never {
while (true) {}
}
never 是所有类型的子类型,它可以给所有类型赋值,但是除了 never 自身以为,其他类型都不能为 never 赋值。
比如我们可以把 never 作为接口类型下的属性类型,用来禁止写接口下特定的属性,示例代码如下:
const props: {
id: number,
name?: never
} = {
id: 1
}
props.name = null; // ts(2322))
props.name = 'str'; // ts(2322)
props.name = 1; // ts(2322)
静态类型检测
在编译(转译)时期,TypeScript 编译器将通过对比检测变量接收值的类型与我们显示注解的类型,从而检测类型是否存在错误。如果两个类型完全一致,显示检测通过;如果两个类型不一致,它就会抛出一个编译期错误,告知我们编码错误。
TypeScript 的语言服务可以和 VS Code 完美集成。因此,在编写代码的同时,我们可以同步进行静态类型检测(无须等到编译后再做检测),极大地提升了开发体验和效率。
类型断言(Type Assertion)
类型断言,告诉 TS 按照我们的方式进行类型检查。
注意:类型断言的操作对象必须满足某些约束关系,否则我们将得到一个 ts(2352) 错误,即从类型“源类型”到类型“目标类型”的转换是错误的,因为这两种类型不能充分重叠。
此外还有一种特殊非空断言,即在值(变量、属性)的后边添加 ‘!’ 断言操作符,它可以用来排除值为 null、undefined 的情况,具体示例如下:
let mayNullOrUndefinedOrString: null | undefined | string;
mayNullOrUndefinedOrString!.toString(); // ok
mayNullOrUndefinedOrString.toString(); // ts(2531)