跳到主要内容

常用类型

原始类型

  • 字符串 string

  • 数字 number

  • 布尔值 boolean

官方不建议使用大写开头 StringNumberBoolean

数组 Arrays

对于 [1, 2, 3] ,其类型可以写成 number[]Array<number>

any

any 类型表示任何类型,可以访问其任何属性、当作函数调用、赋予任意类型的值等:

let obj: any = { x: 0 };
// 以下代码均不会报错
obj.foo();
obj();
obj.bar = 100;
obj = 'hello';
const n: number = obj;

使用 any 会逃避类型检查,对于一些情况是便利的,但非必要的时候不要使用 any

noImplicitAny

给编译器 noImplicitAny 标签会将所有 any 视为报错。

类型标注

可以在声明变量的时候标注类型:

let myName: string = 'Talaxy';

但是 TS 会自己尝试推断类型,有些情况下是可以不标注类型的:

// TS 会自己推断出右值是 `string` 类型
let myName = 'Talaxy';

编译器推断不出类型的时候会判为 any 类型。

函数 Functions

可以明确函数参数和返回值的类型,后续的调用会受到检查:

function add(a: number, b: number): number {
return a + b;
}

add(10, 20); // 30
add('12', 20); // ERROR

匿名函数

TS 会在一些情况下会根据上下文检查函数类型是否正确:

const names = ['Alice', 'Bob', 'Eve'];

// TS 会推断出 `s` 是 `string` 类型
// 传入的回调类型应当为 `(string, number, string[]) => void` ,否则编译器会报错
names.forEach((s) => {
console.log(s.toLowerCase());
});

对象 Objects

对象类型的书写不是很难:

// 属性之间可以用 `,` 或 `;` 隔开
function printCoordinate(pt: { x: number; y: number }) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoordinate({ x: 3, y: 7 });

可选属性

在属性名后面加上 ? 表示属性可选。同时,在访问可选属性的时候请进行空值检查,否则编译器会报错:

// last 属性是可选的
function printName(obj: { first: string; last?: string }) {
// 编译器会判断你有没有进行控制检查,如果没有会报错
if (obj.last !== undefined) {
console.log(obj.last.toUpperCase());
}

// 或者使用最新的 JavaScript 语法(若为空则输出 `undefined` )
console.log(obj.last?.toUpperCase());
}

// 以下代码均不会报错
printName({ first: 'Bob' });
printName({ first: 'Alice', last: 'Alisson' });

联合类型 Union Types

定义一个联合类型

function printId(id: number | string) {
console.log('Your ID is: ' + id);
}

printId(101); // => "Your ID is: 101"
printId('202'); // => "Your ID is: 202"
printId({ myID: 22342 }); // ERROR: 不能将 `{ myID: number}` 类型赋值给 `string | number` 。

使用联合类型变量

在上述例子中,你可以直接调用 numberstring 的共同属性方法。如果你想针对其中一个类型( TS 中称为 Narrowing ),你需要对变量类型进行检查,不管是用 if 语句还是 switch 语句判断:

function printId(id: number | string) {
if (typeof id === 'string') {
console.log(id.toUpperCase());
} else {
console.log(id);
}
}

对于数组你也可以直接使用 Array.isArray(x)

有一个很经典的例子:

// 返回类型将为 `number[] | string`
function getFirstThree(x: number[] | string) {
// 这里的 `slice` 方法为 `number[]` 和 `string` 共有,所以不需要 Narrowing
return x.slice(0, 3);
}

类型别名

类型别名的语法为:

type Point = {
x: number;
y: number;
};

function printCoordinate(pt: Point) {
// ...
}

printCoordinate({ x: 100, y: 100 });

联合类型一样适用:

type ID = number | string;

类型别名并非新类型,类型别名变量在使用中会以真实类型面貌呈现。

接口 Interfaces

接口定义了一个类型必要的属性:

interface Point {
x: number;
y: number;
}

function printCoordinate(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}

let coor = { x: 100, y: 200, z: 300 };
printCoordinate(coor);

上面的例子中,由于 coor 符合 Point 属性要求,所以传参成功。

字面量赋值的时候,应当完全满足接口类型:

// ERROR: 不能将类型 `{ x: number; y: number; z: number; }` 分配给类型“Point”。
let coor: Point = { x: 100, y: 200, z: 300 }; // ERROR

类型断言

在上述的例子中,我们可以明确类型来处理报错:

printCoordinate({ x: 100, y: 200, z: 300 } as Point);

let coor: Point = { x: 100, y: 200, z: 300 } as Point;

还有一些情况,比如你在使用 document.getElementById 的时候,TS 只会知道返回了个 HTMLElement 类型的东西,但是你能肯定它返回的类型为 HTMLCanvasElement 。这种情况下可以使用类型断言:

const myCanvas = document.getElementById('main_canvas') as HTMLCanvasElement;

或者用中括号语法(但不能在 .tsx 文件中使用):

const myCanvas = <HTMLCanvasElement>document.getElementById('main_canvas');

类型断言代码会在编译后去除,不会影响运行时行为。

两个无包含关系的类型是不能用类型断言的:

const x = 'hello' as number; // ERROR

有的时候你可能比 TS 更了解代码,你可以通过两段断言进行强制转换:

// 第一次先转为 `any`(或 `unknown` ),第二次再转为目标类型
// 圆括号可以去除
const a = expr as any as T;

字面量类型

字面量本身也可以作为一种类型,可以在声明中应用:

let x: 'hello' = 'hello';
x = 'hello'; // OK
x = 'howdy'; // ERROR

这其实等价于:

// x 的类型为 "hello"
const x = 'hello';

配合上联合类型,可以指定值集合:

function printText(s: string, alignment: 'left' | 'right' | 'center') {
// ...
}
printText('Hello, world', 'left');
printText("G'day, mate", 'centre'); // ERROR

需要记住的是,string 变量并非能用在字面量类型上的:

const req = { url: 'https://example.com', method: 'GET' };
// TS 并不知道 req.method 是什么,所以只能报错
handleRequest(req.url, req.method); // ERROR

非空断言

可以用 ! 来否定一个类型为空:

function liveDangerously(x?: number | null) {
console.log(x!.toFixed()); // OK
}

枚举 Enums

枚举 Enums

参考

Everyday Types - TypeScript

cannot redeclare block scoped variable (typescript) - Stack Overflow