一、TypeScript简介
- TypeScript由微软开发,是基于javaScript的一个扩展语言。
- TypeScript包含了JavaScript的所有内容,即:TypeScript是JavaScript的超集,
- TypeScript增加了:静态类型检查、接口、泛型等很多现代开发特性,因此更适合大型项目的开发。
- TypeScript需要编译为JavaScript,然后交给浏览器或其他JavaScript运行环境执行。
二、TypeScript出现原因
1. js存在以下问题:js不会报错,不利于项目维护
- 不清不楚的数据类型
- 有漏洞的逻辑
- 访问不存在的属性
- 低级拼写错误
2.ts支持静态类型检查
在代码运行前进行检查,发现代码的错误或不合理之处,减小运行时异常的出现的几率
3.TypeScript的代码结构更加清晰,便于维护
三、TS编译
从html文件引入编译后的js文件
- 全局安装ts
npm install -g typescript
- 初始化
tsc init
3.tsc --watch 监听ts文件
tsc --watch xx.ts
四、TS数据类型
1. js数据类型
- 基本类型 :string、number、boolean、null、undefined、symbol;
- 引用/对象类型:String、Number、Boolean、Array、Function、Date、Error、Math、RegExp、Global、Object
2. TS新增类型
2.1 any:任意类型。
any类型可以赋值给任意类型变量,对定义类型变量产生破坏
2.2 unknown:未知类型
(1) 可以理解为类型安全的any,适用于:不确定数据的具体类型
(2)解决unknown报错方法(typeOf、断言)
2.3 never:任何值都不是,不能有任何值,几乎用不到
(1) 几乎不用never去直接定义变量,没有意义
(2) never一般是TS主动推断出的
(3) never可用于限制函数的类型(函数永远也执行不完或者直接抛出异常的情况返回nerver)
2.4 void:通常用于函数返回值声明【函数不返回任何值/返回值为空,调用者也不应依赖其返回值做任何操作】
注意:不能接受void定义的函数返回值做操作,即使函数隐式返回undefined
2.5 object(object和Object):实际应用很少,范围太宽
(1) object
(2) Object(除了null和undefined 都可以存)
(3) 声明对象类型
1)字面量类型声明(“ ?”为可选属性)
2)索引签名:允许定义对象可以具有
任意数据量的属性
,这些属性的键和类型是可变的,常用于描述类型不确定的属性,(具有动态属性的对象)
(4) 声明函数类型
```js
注意:
1.TS 中的=>在函数类型声明时表示函数类型,描述其参数类型和返回类型
2.JS 中的=>是一种定义函数的语法,是具体函数的实现
3.函数类型声明还可以使用接口,自定义类型等方式
```
(4) 声明数组类型
2.6 tuple元组
元组是一种特殊的数组类型
,可以存固定数量
的元素,并且每个元素的类型是已知
的且可以不同
。元组用于精确描述一组数值的类型,?表示可选元素
2.7 enum枚举(重点)
作用:增加代码可读性,便于后期维护
(1) 数字枚举
数字枚举一种最常见的枚举类型,其成员的值自动递增
且数字枚举还具备反向映射
的特点,在下面
代码的打印中,不难发现:可以通过值来获取对应的枚举成员名称。
不给初始值,默认值从0开始自动递增,否则从当前值递增
(2) 字符串枚举
会丢失反向映射特点
(3) 常量枚举
会减少编译后生成的js代码量,提高运行时的性能
- 使用常量枚举,编译后js文件只生成我们需要的js代码
- 不使用常量枚举,编译后会生成一些额外的js代码
3.两个自定义类型方式
3.1 type(重点)
type可以为任意类型创建别名,让代码更简洁,可读性更强,同时能更方便的进行类型复用和扩展
(1) 基础用法
(2) 联合类型(或类型 “ | ”)
联合类型是一种高级类型,值可以是类型中的一种
(3)交叉类型(且类型 “ & ”)
允许多个类型合并为一个类型,合并后会拥有类型所有成员,常用于对象类型
(4)特殊情况
在函数定义时,限制函数返回值为void,那么函数得返回值必须是空
使用类型声明限制函数返回值为void时,ts并不会严格要求函数返回空
原因:是为了确保如下代码成立,我们知道Array,prototype.push的返回一个数字,而Array.prototy
pe,forEach方法期望其回调的返回类型是void
3.2 interface(重点)
interface是一种定义结构
的方式,主要作用是为:类、对象、函数等规定一种契约,这样可以确保
代码的一致性和类型安全,但要注意interface只能定义格式
,不能包含任何实现
!
(1) 定义类结构
使用implements(实现)关键字
interface PersonInterface {
name: string;
age: number;
speak: (n: number) => void;
}
class Person implements PersonInterface {
constructor(public name: string, public age: number) {}
speak(n: number) {
for (let i = 0; i < n; i++)
console.log(`输出${i}次,我叫${this.name},今年${this.age}岁`);
}
}
const p = new Person("张三", 18);
p.speak(3);
输出显示
一个类可以实现多个接口
interface FlyInterface {
fly(): void;
}
interface SwimInterface {
swim(): void;
}
class Duck implements FlyInterface, SwimInterface {
fly() {
console.log("鸭子可以飞");
}
swim() {
console.log("鸭子可以游泳");
}
}
(2) 定义对象结构
接口当作对象的类型使用
interface UserInterface {
name: string;
age?: number; //可选
readonly gender: "男" | "女"; //只读
run: (n: number) => void;
}
const user: UserInterface = {
name: "张三",
age: 18,
gender: "男",
run: (n) => {
console.log(`我跑了${n}米`);
},
};
user.name = "李四";
user.run(4);
// user.gender = "other"; //报错:无法为“gender”赋值,因为它是只读属性。
(3) 定义函数结构
interface CountInterface {
(a: number, b: number): number;
}
const count: CountInterface = (a, b) => {
return a + b;
};
(4) 接口之间的继承
interface PersonInterface {
name: string;
age: number;
}
interface StudentInterface extends PersonInterface {
grade: string;
}
const student: StudentInterface = {
name: "张三",
age: 18,
grade: "高一",
};
(5) 接口自动合并(接口可重复定义)
interface PersonInterface {
name: string;
age: number;
}
interface PersonInterface {
gender: string;
}
const person: PersonInterface = {
name: "张三",
age: 18,
gender: "男",
};
总结:何时使用接口?
- 定义对象的格式:描述数据模型、AP1响应格式、配置对象等等,是开发中用的最多的场景。
- 类的契约:规定一个类需要实现哪些属性和方法。
- 自动合并:一般用于扩展第三方库的类型,这种特性在大型项目中可能会用到。
(6) interface和type的区别
-
相同:interface和type 都可以用于定义对象结构,两者在许多场景是可以互换的。
-
不同:
interface:更专注于定义
对象和类的结构
,支持继承
、合并
;type:可以定义
类型别名,联合类型,交叉类型
,但不支持继承和合并。
(7) interface和抽象类的区别
-
相同:都用于定义一个
类的格式
-
不同:
接口:只能描述
结构
,不能有任何实现代码
,一个类可以实现多个
接口。抽象类:既可以包含
抽象方法
,也可以包含具体方法
,一个类只能继承一个
抽象类
4. 泛型
泛型允许我们在定义函数、类或接口时,使用类型参数来表示未指定的类型
,这些参数在具体使用
时才被指定具体的类型
。泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性
(1) 泛型函数
//泛型可以使用任意参数,但约定用大写字母
function logData<T>(data: T) {
console.log(data);
}
logData<number>(100);
logData<string>("hello");
(2) 泛型可以有多个
function logData<T, U>(data1: T, data2: U): T | U {
return Date.now() % 2 == 0 ? data1 : data2;
}
console.log(logData<number, string>(101, "hello"));
(3) 泛型接口
interface Person<T> {
name: string;
age: number;
extra: T;
}
type Company = {
address: string;
salary: number;
};
const user1: Person<number> = {
name: "张三",
age: 18,
extra: 100,
};
const user2: Person<string> = {
name: "李四",
age: 18,
extra: "附加信息",
};
const user3: Person<Company> = {
name: "王五",
age: 30,
extra: {
address: "北京市",
salary: 20000,
},
};
(4) 泛型类
class Person<T> {
constructor(public name: string, public age: number, public extraInfo: T) {}
introduce() {
console.log(this.name, this.age, this.extraInfo);
}
}
type Company = {
address: string;
salary: number;
};
const p1 = new Person<string>("张三", 18, "附加信息");
p1.introduce();
const p2 = new Person<Company>("张三", 18, {
address: "北京市",
salary: 200000,
});
p2.introduce();
输出显示
五、类型声明文件
类型声明文件是TypeScript中的一种特殊文件,通常以.d.ts作为扩展名。它的主要作用是为现有的JavaScript代码提供类型信息
,使得TypeScript能够在使用这些JavaScript库或模块时进行类型检查和提示。
六、常见的TS工具类(重点)
1. Omit (省略/剔除)
从传入的类型中剔除
自己不需要
的部分形成新的定义类型
2. pick (挑选)
从传入的类型中挑选
自己需要的
部分形成新的定义类型
3. Partial (可选)
将传入的类型全部(必选项&可选项)变为可选
项
4.Required (必选的)
将传入的类型全部(必选项&可选项)变为必选
项,与Partial相反
5.ReadOnly (只读)
将传入的类型全部(必选项&可选项)变为只读
项,
6. Exclude
处理联合类型,剔除A中包含B的部分(A - A∩B)
7. Extract
处理联合类型,从A中选出A,B共同部分(A∩B)
8. Record
Record<K,T>用于定义一个对象类型,其中键的类型为 K
,值的类型为 T