TypeScript
[TOC]
1.基本数据类型
1.1js中基本数据类型
首先TS支持JavaScript中内置的所有基本类型:
let str:string = “hmbb”;
let num:number = 12;
let bol:boolean = false;
let ud:undefined = undefined;
let nu:null = null;
let big:bigint = 100n;
let sym:symbol = symbol(“1”);
在TypeScript中,null和undefined是所有类型的子类型,也就是这两中类型的值可以赋值给任何一个类型,而不报错。
1.2any类型
当给一个变量设置为any类型,那这个变量就没有任何限制,任何数据类型都可以赋值给这个变量。
不要滥用any类型,这会导致TypeScript的类型检查功能失效。
1.3 unknown类型
unknown类型比any类型更加安全,所有的数据类型都可以赋值给unknown类型的变量。
只是unknown类型不可以调用属性和函数。
2.接口类型
2.1 接口基本使用
接口就是一个约束作用:
1 | interface Person{ |
如果在上面的student对象中加入其他的属性就会报错:
1 | let student:Person = { |

2.2 可选属性
如果我们想要设置某个属性是可以有无的,我们可以设置一个可选属性:?:。
我们将上面Person接口重写一下:
1 | interface Person{ |
此时我们student就不会出现报错了。
2.3 只读属性
如果要确保某个变量不能被修改,只能读取,我们可以使用只读修饰:readonly。
我们将Person中的age改为只读属性(年龄不可以随意修改)。
1 | interface Person{ |
报错:

党我们把属性设置为只读的时候,就不可以进行二次修改了,但是可以正常读取。
2.4 继承
当我们想要把两个接口结合在一起的时候,我们可以使用extends继承。
1 | export interface Person { |
如果我们将score的值设置为一个字符串,就会报错:

2.5 补充
当我们在同一个文件夹下,不同的文件中,声明了同一个接口(或者其他类型),使用的变量名相同时,TypeScript也会报错:

主要有两种方法解决:
- 使用使用
export和import关键字:在每个文件中,将你想要在其他文件中使用的内容通过export关键字进行导出,然后在需要使用这些内容的文件中使用import关键字引入。这样,每个文件都成为一个独立的模块,它们的作用域不会互相干扰。
导出接口(interface.ts)
1 | export interface Student{} |
在另一个文件导入接口
1 | import {Student} from "./interface.ts" |
- 使用命名空间(namespace):命名空间是一种在全局环境中组织代码的方式,可以避免不同文件中的变量名冲突。通过在不同文件中使用相同的命名空间,可以确保它们的内容不会相互干扰。
定义命名空间
1 | // 这里将空间命名为P |
在另一个文件使用该命名空间的接口
1 | const student: P.Student = { |
推荐使用第一种方法。
3. 对象类型
在TypeScript中,对象类型并不是单单指object.
3.1 原始数据类型中的对象
在原始值类型中,有下面几种对象类型:
| 原始数据类型 | 对应的对象 |
|---|---|
| number | Number |
| boolean | Boolean |
| null | Null |
| string | String |
| undefined | Undefined |
原始数据类型与其对象有下面几个区别:
存储位置不同:原始数据类型直接存放在栈内存当中,但是对象存放在堆内存中。
传值方式不同:原始数据类型按值传递,对象是按引用传递。
所以定义变量类型的时候,使用原始数据类型或者对象类型都是可以的,只是有上面的两点区别。
3.2 Object类型
Object类型是所有Object类的实例,如果使用Object来限制变量类型,那么值类型(原始数据类型)和引用类型(原始数据的对象类型)都会指向Object。
1 | let a:Object = 12; |
3.3 object类型
object 代表所有非值类型(非原始类型)的类型,例如 数组 对象 函数等,常用于泛型约束。
它只支持引用数据类型,对于原始数据类型不支持。
1 | let a:object = 12; // 报错 |

对于引用数据类型就不会报错。
4. 数组类型
4.1 普通声明方式
使用数据类型[]方式来声明。
1 | let arr1: number[] = [1, 2, 3, 4]; |
使用这种方法定义时,前面的数据类型是什么,后面数组里面的数据类型也只能是这种或者是这种的子类。
否则就会报错:
1 | let arr1: number[] = [1, 2, 3, "q",4]; // 不能将类型“string”分配给类型“number”。 |
4.2 使用泛型来声明
Array<类型名>
1 | let arr2:Array<boolean> = [false,true,false]; |
同样数组里面只能存放定义时的数据类型或者它的子类型。
4.3 类数组 – arguments
类数组就是所有参数的集合
在TS中,有一个内置的类型:IArguments
1 | function getArr(a: number, b: number, ...arg: any[]): void { |
IArguments类型其实就是:
1 | interface IArguments{ |
4.4 使用接口来声明
使用接口来定义
1 | interface Person { |
5.函数
5.1 普通方式定义
TS可以限制函数的参数类型,以及函数的返回值类型
比如:
1 | function fn(name:string,age:number):string{ |
上面的函数第一个参数只能传入一个字符串类型,第二个参数只能传入number类型,并且返回值只能是字符串类型。
如果调用函数时,传入的参数或者返回的数据类型与定义类型不符,就会报错。

5.2 对象形式定义
使用接口或者type 的方式
1 | interface User{ |
5.3 函数重载
函数重载就是:方法名相同,参数类型不同,返回值类型也可以不相同。
执行重载函数的时候,会从上往下执行,所以需要把最精确的类型放在最前面。
1 | function fn(params:number):void//第一套规则 |
执行器从上往下执行,一旦匹配到合适的函数规则,就不再往下继续匹配,直接开始执行函数体里面的内容。
6.联合类型|交叉类型|类型断言
6.1 联合类型
当我们一个变量可能会存放两种及其以上的数据类型,这个时候我们可以使用联合类型。
1 | let a:number|string = 12; |
同理这个方法在函数的参数一样可以使用。
6.2 交叉类型
前面的联合类型是对基础的单个数据类型进行了扩充,交叉数据类型就是将多种数据类型的集合(比如接口)进行扩充。
1 | interface Per1{ |
6.3 类型断言
类型断言可以使用: 值 as 类型 或者 <类型>值
推荐前面那一种写法,因为在TSX中,<>可能会引起误会。
- 类型断言的用途
(1)将一个联合类型推断为其中一个类型
(2)将一个父类断言为更加具体的子类
(3)将任何一个类型断言为 any
(4)将 any 断言为一个具体的类型