typescript-learning

typescript

类型注解

接口

在typescript当中,只要两个类型内部的结构兼容,那么这两个类型就是兼容的,可以有多余的属性

1
2
3
4
5
interface Person {
firstName: string;
lastName: string;
}
let user = { firstName: "Jane", lastName: "User" };
  • 可选属性

    对可能存在的属性进行预定义,可以捕获引用不存在属性时候的错误(静态检测)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface SquareConfig {
color?: string;
width?: number;
}

function createSquare(config: SquareConfig): { color: string; area: number } {
let newSquare = {color: "white", area: 100};
if (config.color) {
// Error: Property 'clor' does not exist on type 'SquareConfig'
newSquare.color = config.clor;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}

let mySquare = createSquare({color: "black"});
  • 只读属性

    readonly对应属性,const对应变量,只能够在对象刚刚创建属性的时候修改其值

1
2
3
4
5
6
7
interface Point {
readonly x: number;
readonly y: number;
}

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
  • implements

    接口可以被当做公用的方法被继承

1
2
3
4
5
6
7
8
interface ClockInterface {
currentTime: Date;
}

class Clock implements ClockInterface {
currentTime: Date;
constructor(h: number, m: number) { }
}

数据类型

  • 数组泛型Array<元素类型>
  • 元组:已知元素数量和类型的数组,各元素的类型不必相同 let x: [string, number]

    可以越界访问,是联合的类型(赋值)

  • any,适用于在运行阶段当中才确定的值,通过编译阶段的检查
    • 可以用与定义数组类型(不确定有多少中数据类型,元组)
    • 能够在上面调用任意的方法(和object的区别)
  • void 表示没有类型,只能将它赋值为null或者undefined,函数返回值
  • never 无法到达终点的函数的返回值类型

    never是所有类型的子类型,可以赋值给仍和类型,而never类型的变量则无法被任何类型复制(除了never)

具有和面向对象语言同样的思想,constructornew,使用extends进行类的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}

class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}

class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}`

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

注意点

  • constructor当中使用super调用基类的构造函数,调用this之前一定要调用super()
  • 在派生类当中使用super.method调用基类的方法
  • 类当中也可以设置属性为readonly,在声明或者构造函数当中被初始化

函数

1
2
3
4
5
6
7
8
9

function buildName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}

let result1 = builggdName("Bob"); // works correctly now, returns "Bob Smith"
let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"
let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
let result4 = buildName("Bob", "Adams");

如果没有设置成可选参数的话,就不能跟原先js函数的写法传入参数一样

泛型

1
2
3
4
function identity<T>(arg: T): T {
return arg;
}
let output = identity("myString");

如上面所示,泛型函数会自动检测类型。

1
2
3
4
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}

同时可以指定特殊的泛型变量,例如输出数组的长度。如果是其他属性,则要定义泛型约束

1
2
3
4
5
6
7
8
interface Lengthwise {
length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}

模块

typescript当中内部模块成为命名空间,外部模块成为模块

  • 使用as进行重命名
1
2
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
  • 默认导出

    默认导出当中可以实现自定义名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const numberRegexp = /^[0-9]+$/;

export default function (s: string) {
return s.length === 5 && numberRegexp.test(s);
}

import validate from "./StaticZipCodeValidator";

let strings = ["Hello", "98052", "101"];

// Use function validate
strings.forEach(s => {
console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);
});