Exploring TypeScript Type Annotations - Built-in Types
关于
作者: zhilidali
欢迎来到 《探索 TypeScript 类型注解》 系列教程。
开篇我们(重新)认识了 TypeScript,本篇探索 TypeScript 的原生数据类型。
目录
正文
1 使用类型注解
let foo = 'TS';
let bar: boolean = foo; // Error: Type 'string' is not assignable to type 'boolean'.ts(2322)
类型注解
Type Annotations
语法 : : type
。如 :boolean
。
作用 :约定变量的数据类型。如约定 bar
为布尔值。
好处 :
- 静态编译时检查类型。如编译器会警告
Type 'string' is not assignable to type 'boolean'
。 - 作为文档。在 VSCode 中将光标移到第二行
bar
上,会提示let foo: string
。
类型推论
Type Inference
foo
的类型没有显示指定,TypeScript 会根据上下文自行推断。let foo = 'TS';
与 let foo: string = TS;
是等价的。
2 基础类型
Primitive Type
- 支持
boolean
、number
、string
、symbol
、undefined
、null
基础类型- 新增
void
、never
基础类型- 新增
any
类型
JS 基础类型
TypeScript 支持 JavaScript 的基础类型
let tsBoo: boolean = false;
let tsNum: number = 0x10;
let tsStr: string = 'ts';
let tsSym: symbol = Symbol('ts');
let tsUnInit: undefined;
let tsEmpty: null = null;
TS 还支持基本包装类型Boolean
、Number
、String
、Symbol
,基本类型为基本包装类型的子类型。
// 基本包装类型 Boolean
let tsBool1: Boolean = new Boolean();
// 基本类型为基本包装类型的子类型
let tsBool2: Boolean = false;
新增基础类型
void
-
void
标识函数没有返回值(返回 undefined)。
function tsVoid(): void {
// 没有 return,即 `return undefined` 时使用
}
void VS. undefined
- 在 JS 中,void 为操作符,总返回 undefined; 而 undefined 在宽松模式下,可作变量。
- 在 TS 中,
void
作为返回值类型时,可用其他类型替换,而undefined
不行。
function bar(callback: () => void) {}
function baz(callback: () => undefined) {}
// foo 返回 number 类型
function foo(): number { return 1; }
bar(foo); // foo 返回的 number 类型替换为 void 类型
baz(foo); // Error:`Type 'number' is not assignable to type 'undefined'.(2345)`)
never
-
never
标识函数不会 return。如抛出异常或生成器函数存在while(true){}
。 -
never
是所有类型的子类型,可赋给任意类型。
function tsNever1(): never {
throw new Error('Throw Exception or never return');
}
function *tsNever2(): never {
while(true) {
// ...
}
}
基础类型兼容
never
前面说过,never
是所有类型的子类型。在 tsconfig.json 中:
-
strictNullChecks
为 false 时,可直接赋给任意类型。 -
strictNullChecks
为 true 时,never
需在赋值后才能使用。
let tsNever: never;
let tsNum: number;
let f = function():never {throw 'never'};
tsNum = tsNever; // `strictNullChecks` 为 true 时,提示 Error。
tsNever = f();
tsNum = tsNever;
any
TS 还增加了 any
类型,当不希望 TS 检查时使用。
- 任意类型赋值给
any
类型或any
类型赋值给任意类型 (never 除外) 均不会报错。
any
let tsAny: any = 'any value';
let tsNum: number = tsAny; // 可赋值给任意类型
tsAny = true; // 可被赋值任意类型
undefined && null
undefined
、null
为子类型。在 tsconfig.json 中:
-
strictNullChecks
为 false 时,undefined、null 可赋值给除never
外的任意类型的变量。 -
strictNullChecks
为 true 时,undefined 只能赋值给void
、any
类型的变量。
let tsNum: number = undefined;
let tsVoid: void = undefined;
3 引用类型
Reference Type
- 支持 Object、Array、Date、RegExp、Error、Function、Class 等类型
- 新增 Tuple、Enum 类型
Object
object
描述(只读)对象类型
let tsObj1: object = { a: 1 };
tsObj1.x = 2; // Error: Property 'x' does not exist on type 'object'.
Array
三种定义方式(后两种详见下篇):
- _类型后加
[]
_,即T[]
- Array Generic 数组泛型 :
Array
ReadonlyArray
- Number Index Signature 数值索引签名 : 通过
interface
定义类型
let tsArr1: string[] = ['foo'];
// 数组范型
let tsArr2: Array = ['foo'];
let readonlyArr: Array = ['foo']; // 只读数组
// 数值索引签名
interface IdxType { [index: number]: string } // type IdxType = string[];
let tsArr3: IdxType = ['foo'];
Tuple
元组:已知元素数量和类型的数组
let tsTuple: [string, number] ;
tsTuple = ['foo', 1];
tsTuple = [1, 'foo']; // Error
tsTuple[0].toUpperCase();
tsTuple[1].toUpperCase(); // Error
// 访问越界元素时会使用联合类型: (string | number)
tsTuple[2] = 'bar';
tsTuple[2] = 2;
tsTuple[2] = false; // Error
Enum
枚举: 定义一组命名常量(枚举成员只读)
- Numeric enums 数值枚举 : 可定义初始值(默认为 0),后面根据初始值递增。
- String enums 字符串枚举
- Heterogeneous enums 异构枚举
// Numeric enums
enum Color { Red = 2, Green, Blue };
/* 编译器反向映射为
var Color;
(function(Color) {
Color[(Color["Red"] = 2)] = "Red";
Color[(Color["Green"] = 3)] = "Green";
Color[(Color["Blue"] = 4)] = "Blue";
})(Color || (Color = {}));
*/
let num: Color = Color.Green; // 3
let str: string = Color[3]; // Green
// String enums
enum Response { No = 'NO', Yes = 'YES' }
// Heterogeneous enums
enum HeterogeneousEnum { No = 0, Yes = "YES" }
Date RegExp Error
let date: Date = new Date();
let reg: RegExp = /\.ts$/;
let err: Error = new Error('error');
Function
描述参数和返回值类型
(paramter: T): U
描述函数定义: (paramter: T) => U
描述函数变量
// 函数声明
function fn1(s: string): string {
return s;
}
// 箭头函数表达式
let fn2 = (s: string): string => s;
// 函数变量 fn
let fn3: (str: string) => string = fn2;
参数
- optional parameters 可选参数 :
foo?: T
- default parameters 默认参数 :
foo: T = value
- rest parameter 剩余参数 :
...rest: T[]
let fn2 = (
s: string, // 必选参数
b: string = '', // 默认参数
c?: string, // 可选参数;位于必选参数后面
...d: string[] // 剩余参数;位于参数最后
): string => s;
重载
// Overload
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
Class
TS 保留并增添了功能 (目前 TS 与 ES 的类表现不一致)
ES :
class F {
constructor(msg) {
this.foo = msg;
}
getFoo() {
return this.foo;
}
}
class B extends F {
constructor(msg) {
super(msg);
}
getFoo() {
return 'b' + super.getFoo();
}
}
TS :
class F {
foo: string
constructor(msg: string) {
this.foo = msg;
}
getFoo() {
return this.foo;
}
}
class B extends F {
constructor(msg: string) {
super(msg);
}
getFoo() {
return 'b' + super.getFoo();
}
}
结语
本篇介绍了 TS 的内置类型,下一篇介绍如何自定义类型。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。