TypeScript 介绍

TypeScript = JavaScript + 类型系统 + 现代语法

TypeScript是JavaScript的一个超集(Superset)。这意味着:

  • 所有合法的JavaScript代码,都是合法的TypeScript代码
  • TypeScript在JavaScript的基础上增加了静态类型检查
  • TypeScript最终会被编译成纯JavaScript运行

TypeScript环境搭建

TypeScript(简称TS),需要nodejs环境,目前推荐使用nvm管理,可参考《NVM的安装与使用》

下面以NodeJS 18为例,安装TypeScript运行环境。使用VS Code新建一个项目,tslearn

安装TypeScript

1
npm i typescript -g

安装执行器

1
npm i tsx -g

测试是否可用

新建一个chapter01-basic-types.ts

1
2
let nums: number[] = [1, 2, 3, 4]
console.log(nums)

使用tsx运行ts代码

1
tsx .\chapter01-basic-types.ts

TypeScript基础类型

  • 数字类型:number
  • 字符串类型:string
  • 布尔类型:boolean
  • 空类型:null
  • 未定义类型:undefined
  • 数组类型:array
  • 对象类型:object
  • 元组类型:tuple
  • 任意类型:any
  • 未知类型:unknow
  • never类型:never
  • 没有返回值类型:void

数字类型 number

  • 整型 number
  • 浮点型 number
  • 大整数 bigint
1
2
3
4
const int_number:number = 100;
const float_number:number = 3.1415;
const bitint_number:bigint = 100n;
console.log(int_number, float_number, bitint_number)

布尔类型 boolean

1
2
3
4
5
6
console.log("-------- 布尔类型 boolean -----------")
const isTrue: boolean = true;
const isFalse: boolean = false;
// 推荐加上类型注解
const isSuccess = true;
console.log(isTrue, isFalse,isSuccess)

字符串类型 string

1
2
3
4
5
console.log("-------- 字符串类型 string -----------")
const str1: string = "Hello";
const str2: string = 'World';
let str3 = `Hello, ${str2}`;
console.log(str1, str2, str3)

空类型 null

1
2
3
console.log("-------- 空类型 null -----------")
const nullValue: null = null;
console.log(nullValue)

未定义类型 undefined

1
2
3
console.log("-------- 未定义类型 undefined -----------")
const undefinedValue: undefined = undefined;
console.log(undefinedValue)

数组类型 []

1
2
3
4
5
6
7
8
console.log("-------- 数组类型 array -----------")
let array1: number[] = [1,2,3,4];
console.log(array1)
let strArray: string[] = ["Hello","World"];
console.log(strArray)
// 可以放不同类型
let strNumArray: (string | number)[] = ["Hello", 1, "World", 2];
console.log(strNumArray)

对象类型 object

1
2
3
4
5
6
7
8
9
10
console.log("-------- 对象类型 object -----------")
let user:object = {
name: "zhangsan",
age: 19
}
console.log(user)
const arr11:object = [1,2,3,4]
console.log(arr11)
const fn1:object = () => {};
console.log(fn1)

对象类型非常宽泛,只能访问对象共有的方法:valueOf()equals()hashCode()toString()等。

1
2
3
4
5
const user:object = {name:"tom",age:18};
// 不能访问具体属性
console.log(user.name) // Error: Property 'name' does not exist on type 'object'.
// 访问toString()方法
console.log(user.toString())

一般用接口来定义对象的熟悉和方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 对象字面量类型(推荐)
const student:{name:string,age:number} = {name:"Jerry",age:20}
console.log(student)


// 通过接口
interface Student {
name:string;
age:number;
}

const stu:Student = {name:"Lucy",age:21}
console.log(stu)

// 通过Record
const map:Record<string,number> = {a:1,b:2,c:3}
console.log(map)

// 通过索引签名
const dict:{[key:string]:any} = {x:1,y:2,z:3}
dict["name"] = "Lucy";
dict["age"] = 21;
console.log(dict)

对于objectObject{}

  • object: 非原始类型,用于任意对象。
  • Object:JS的Object构造函数类型,包含原始类型包装器
  • {}: 空对象类型,除了null/undefined,都支持。

1、需要任意对象时,使用object

2、需要具体结构式: 用interface / 类型别名 / 字面量类型

3、尽量避免使用Object{}作为类型。

元组类型 tuple

和Python一样,元组是固定长度、固定类型的数组。

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
console.log("-------- 元组类型 tuple -----------");
let tuple1: [string, number] = ["Hello", 100];
console.log(tuple1);
let tuple2: [string, number, boolean] = ["World", 200, true];
console.log(tuple2);
// 可选
let tuple3: [string, number, boolean?] = ["Optional", 300];
let tuple4: [string, number, boolean?] = ["Optional", 300, true];
console.log(tuple3);
console.log(tuple4);

// 不定长元素
let tuple5: [string, ...number[]] = ["Numbers", 1, 2, 3, 4];
console.log(tuple5);

//只读元组
let tuple6:readonly [string, number] = ["ReadOnly", 400];
//tuple6[0] = "NewValue"; // Error: Index signature in type 'readonly [string, number]' only permits reading

//具名元组,每个位置都有名字
type userTuple = [name:string,age:number];
// 语义更清晰
let tuple7:userTuple = ["Tom", 18];
console.log(tuple7[0]);
// 当然也可以直接使用字面量
let tuple8:[name:string,age:number] = ["Tom",18];

其主要使用场景:

  • 函数返回多个值
  • CSV行解析
  • 键值对
  • 坐标与几何数据
  • API响应封装等

any类型

在 TypeScript 中, any 是最宽松的类型,表示”任意类型”,会关闭该变量的类型检查。

1
2
3
4
5
6
7
8
9
console.log("-------- any类型 -----------");
let anyValue: any = "Hello";
console.log(anyValue);
anyValue = 100;
console.log(anyValue);
anyValue = true;
console.log(anyValue);
// 可以访问任何属性、调用任何方法
value.foo.bar(); //运行期可能报错

虽然any一时爽,但是维护起来真蛋疼,尽可能不要使用any,不然该叫AnyScript了。

unknown类型

TypeScript 中 unknown类型安全any ,表示”值可以是任何类型,但使用前必须先检查”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
console.log("-------- unknown类型 -----------");
let unknownValue: unknown = "Hello";
console.log(unknownValue);
unknownValue = 100;
console.log(unknownValue);
unknownValue = true;
console.log(unknownValue);

// 不能直接调用
//console.log(unknownValue.toString()); // Error: Object is of type 'unknown'.

// 先做类型检查
if (typeof unknownValue === "string") {
// 使用 typeof检查
console.log(unknownValue.toUpperCase());
} else if (unknownValue instanceof Number) {
// 使用 instanceof检查
console.log(unknownValue.toFixed(2));
} else if (unknownValue as boolean) {
// 使用类型断言
console.log(unknownValue ? "True" : "False");
}

never类型

TypeScript 中 never 表示 永远不会发生的值 的类型,是 所有类型的子类型 。一般用于抛出异常

1
2
3
4
5
6
7
8
9
10
11
console.log("-------- never类型 -----------");
// 抛异常
function error(message: string): never {
throw new Error(message);
}
// 死循环
function infiniteLoop(): never {
while (true) {
// 死循环
}
}

void类型

和其他语言一样,void 表示 函数没有返回值 或 返回值被忽略 。

1
2
3
4
console.log("-------- void类型 -----------");
function printMessage(message: string): void {
console.log(message);
}