Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

TypeScript 基础

介绍

TypeScript 是 JavaScript 的一个超集,添加了静态类型和基于类的面向对象编程。
使用 .ts 作为文件扩展名。

安装

  1. 使用 npm(需要安装 Node.js)。在终端中运行以下命令:
1
npm install -g typescript
  1. 使用TypeScript VSCode 扩展

数据类型

布尔值(boolean)

布尔值用于存储true/false值。

1
let isDone: boolean = false;

数字(number)

TS里的所有数字都是浮点数。 这些浮点数的类型是 number
并且支持二进制、八进制、十进制与十六进制字面量面量。

1
2
3
4
let binary: number = 0b1010; // 二进制
let octal: number = 0o744; // 八进制
let decimal: number = 42; // 十进制
let hexadecimal: number = 0x2a; // 十六进制

字符串(string)

字符串用于处理网页或服务器端的文本数据。

1
let greeting: string = "hello";

空值 Void、Null 和 Undefined

nullundefined 是两个不同的类型。

  • void。表示没有任何类型,比如函数没有返回值时。
  • null 表示一个空值,通常用于表示“无”或“未知”。
  • undefined 表示一个变量未被赋值。

默认情况下 nullundefined 是所有类型的子类型。

Any

any 类型表示任何类型的值。使用 any 类型可以让你在编程时更加灵活,但也会失去类型检查的好处。

Never

never类型表示的是那些永不存在的值的类型。
never 类型是任何类型的子类型,也可以赋值给任何类型。
然而,没有类型是 never 的子类型或可以赋值给 never 类型,即便是any也不行。

数组(Array/[])

数组用于存储多个相同类型的集合。
可以使用类型[]或使用Array<类型>来表示数组。

1
2
let numbers: number[] = [1, 2, 3];
let fruits: Array<string> = ["apple", "banana", "orange"];

元组(Tuple)

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

当访问一个已知索引的元素,会得到正确的类型:

1
2
3
4
let tuple: [string, number];
tuple = ["hello", 10]; // 正确
console.log(tuple[0].substring(1)); // 正确
console.log(tuple[1].toFixed(2)); // 正确

枚举(Enum)

枚举类型可以为一组数值赋予友好的名字。
默认情况下,从 0 开始为元素编号。

枚举类型可以由枚举的值得到它的名字。

1
2
3
4
5
6
7
8
9
10
enum Color {
Red, // 0
Green, // 1
Blue, // 2
}
let c: Color = Color.Green;

let colorName: string = Color[2];
// 显示'Green'因为上面代码里它的值是2
console.log(colorName);

也可以手动的指定成员的数值。
枚举类型支持指定数字、字符串枚举和异构枚举。

1
2
3
4
5
6
enum Color {
Red = "红色",
Green = "绿色",
Blue = "蓝色",
White = 0xffffff,
}

对象(Object)

object 表示非原始类型

函数(Function)

以像变量一样被传递和使用。

1
2
3
function add(x: number, y: number): number {
return x + y;
}

默认参数、可选参数与剩余参数

1
2
3
4
5
6
7
8
9
10
11
12
// firstName = "John" 是默认参数
// lastName? 是可选参数
// ...restOfName: string[] 是剩余参数
function buildName(
firstName: string = "John",
lastName?: string,
...restOfName: string[]
): string {
if (lastName)
return firstName + " " + lastName + " " + restOfName.join(" ");
else return firstName;
}

泛型

泛型用于创建可重用的组件

泛型函数
通过在函数名后面添加 <T,...> 来定义泛型函数,其中 T... 是类型变量,可以在函数体内当作类型使用。
使用 extends 关键字来约束类型变量。

1
2
3
4
5
6
7
8
function identity<T extends U, U>(arg: T): T {
return arg;
}

// 输出: 42
console.log(identity<number, string>(42));
// 输出: Hello
console.log(identity<string, string>("Hello"));

泛型类

1
2
3
4
5
6
7
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;

接口(Interface)

接口用于定义对象的结构和类型。

支持可选属性、只读属性、函数类型、索引类型等。

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
31
32
33
34
interface Person {
// 只读属性
readonly id: string;
name: string;
// 可选属性
age?: number;
// 函数类型
greet: () => void;
// 索引类型
[index: string]: string | number | (() => void);
}

const user: Person = {
id: "123",
name: "张三",
age: 30,
greet: () => {
console.log(`Hello, my name is ${user.name}`);
},
address: "北京市",
};

// { id: "123", name: '张三', age: 30, address: '北京市' }
console.log(user);
// 北京市
console.log(user["address"]);

try {
// 无法修改只读属性
user.id = "124";
} catch (error) {
// Error: Cannot assign to 'id' because it is a read-only property.
console.error(error);
}

使用 implements 关键字来实现重写接口

  • 可以重写属性和方法

使用 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
interface Animal {
name: string;
speak(): void;
}

interface Dog extends Animal {
sound: string;
speak(): void; // 重写方法
}

class Labrador implements Dog {
name: string;
// 重写类型
sound: string[];

constructor(name: string, sound: string[]) {
this.name = name;
this.sound = sound;
}

speak(): void {
console.log(`${this.name} says ${this.sound.join(", ")}`);
}
}

交叉类型(Intersection Types)

交叉类型是将多个类型合并为一个类型。
可以把现有的多种类型叠加到一起成为一种类型,其包含了所需的所有类型的特性。
使用&符号来表示交叉类型。

Person & Serializable & Loggable同时是 PersonSerializableLoggable
就是说这个类型的对象同时拥有了这三种类型的成员。

联合类型(Union Types)

联合类型表示一个值可以是几种类型之一。
使用|符号来表示联合类型。
number | string | boolean表示一个值可以是 numberstring,或 boolean

类型操作

类型断言

类型断言是一种手段,可以用来告诉编译器变量的实际类型。
类型断言有两种形式:

  1. 尖括号语法: (<类型>变量名)
  2. as 语法:(变量名 as 类型)

类型保护

当类型可能是几个类型之一时,需要每次使用类型断言使编译器知道其确切类型。
TS 提供了多种方式来来做到这一点。

  1. 使用 typeof 进行类型保护
1
2
3
4
5
6
7
8
9
10
// 使用 typeof 进行类型保护
function example(value: string | number) {
if (typeof value === "string") {
// 在这个分支中,value 的类型被缩小为 string
console.log(value.toUpperCase());
} else {
// 在这个分支中,value 的类型被缩小为 number
console.log(value.toFixed(2));
}
}
  1. 使用 instanceof 进行类型保护
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 使用 `instanceof` 进行类型保护
class Dog {
bark() {
console.log("Woof!");
}
}

class Cat {
meow() {
console.log("Meow!");
}
}

function example(animal: Dog | Cat) {
if (animal instanceof Dog) {
// 在这个分支中,animal 的类型被缩小为 Dog
animal.bark();
} else {
// 在这个分支中,animal 的类型被缩小为 Cat
animal.meow();
}
}

  1. 使用自定义的类型保护函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 使用 类型保护函数,函数返回值类型为:`变量名 is 类型`
    interface Dog {
    bark:() => void;
    }
    interface Cat {
    meow: () => void;
    }

    function example(animal: Dog | Cat) {
    const isDog = (animal: Dog | Cat): animal is Dog => {
    return (animal as Dog).bark !== undefined;
    }

    if (isDog(animal)) {
    // 在这个分支中,animal 的类型被缩小为 Dog
    animal.bark();
    } else {
    // 在这个分支中,animal 的类型被缩小为 Cat
    animal.meow();
    }
    }

typeof只能用于基本类型的类型保护,instanceof只能用于构造函数的类型保护。
而自定义的类型保护函数可以用于任何类型的类型保护。

映射类型

TypeScript提供了从旧类型中创建新类型的一种方式。 在映射类型里,新类型以相同的形式去转换旧类型里每个属性。
一些常用的映射类型有:

  • Partial<T> – 将类型T的所有属性变为可选。
  • Required<T> – 将类型T的所有属性变为必需。
  • Readonly<T> – 将类型T的所有属性变为只读。
  • Pick<T, K> – 从类型T中选择一组属性K来构造新类型。
  • Exclude<T, U> – 从T中剔除可以赋值给U的类型。
  • Extract<T, U> – 提取T中可以赋值给U的类型。
  • NonNullable<T> – 从T中剔除null和undefined。
  • ReturnType<T> – 获取函数返回值类型。
  • InstanceType<T> – 获取构造函数类型的实例类型。

参考资料

TypeScript 官方文档

关于本人

HaiYao 的博客
Git 主页

评论