TypeScript总结

开发环境搭建

安装Node.js

安装Typescript

npm i -g typescript

创建.ts文件即可开始编写TS代码

TS类型声明

let 变量:类型
let 变量:类型 = 值
function fn(参数:类型,参数:类型):类型{…}

  • 若声明和赋值同时进行,则自动进行类型判断

TS类型介绍

类型说明

  • number
  • string
  • boolean
  • any:任意类型,可以赋值给任意变量
  • unknown:类型安全的any,无法给其他(非unknown)变量赋值
  • void:空值,函数默认的返回值(没有返回值)
  • never:不能是任何值,如函数throw error
  • 隐式any:声明变量时不指定类型,自动判断为any
  • 定义对象结构
  • let obj : {name : string, [propName : string] : any}

  • 定义函数结构
  • let fun : (a : number, b : number)=>number

  • 定义数组结构
  • let arr:string[]
    let arr : Array<number>

  • tuple:元组——固定长度的数组
  • 变量:[类型,类型,…]

  • enum:枚举
  • enum 类名{键:值,键:值,…}

修饰语法:

  • 可以使用|连接多个类型
  • 断言:变量 as 类型 / <类型>变量
  • :类比正则,该属性可有可无
  • 类型别名
  • type 别名 = 类型(类型范围)

TS编译

编译单文件

tsc XXX.ts

监视并编译文件

tsc XXX.ts -w

编译所有文件

在目录下创建tsconfig.json文件,进行相关配置
详细配置参考文末视频讲解

TS面向对象

  • 对象:属性和方法的集合
  • 类:对象的抽象表现形式
  • 实例:根据类生成的具体的对象

定义类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Cat {
// 定义实例属性(通过实例对象访问)
name: string;
// static 定义静态属性(通过类去访问)
static age: number = 3;
// readonly 只读属性,无法修改
readonly color: string = 'white';
// 静态只读属性:仅能通过类读取,且无法修改
static readonly weight:number = 10;
...
// 定义方法(也可以用static修饰)
sayHello(){
console.log("喵喵喵~");
}
}
cosnt cat = new Cat();

构造函数和this

通过类创建实例对象时会自动调用constructor()构造函数,内部的this指向要创建的实例对象
通过this.属性名,可以向新创建的实例对象中添加属性

1
2
3
4
5
6
7
8
9
10
class Cat {
// 定义属性
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
const cat = new Cat("咪咪", 3);

继承

  • 通过继承(extends),共享一些公用的属性和方法,减少代码冗余
  • 子类拥有父类所有的方法和属性,且可以添加自己独有的方法和属性(OCP:开闭原则)
  • 若子类中添加了和父类相同的方法,则会覆盖父类中的方法(重写)
1
2
3
4
5
6
7
8
9
10
11
class Animal {
// 定义属性
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class Dog extends Animal {};
const dog = new Dog("汪汪", 4);

super

  • 子类中,super指向父类,可以通过super.方法名()调用父类中的方法
  • 若子类创建新的属性,子类的constructor()会覆盖父类,导致继承未实现,此时需要在子类的构造函数中通过super(属性名:类型,...)把父类中的constructor()拿到
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
// 父类
class Animal {
// 定义属性
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 定义方法
sayHello() {
console.log("动物在叫");
}
}
// 子类
class Dog extends Animal {
// 定义属性
weight: number
constructor(name: string, age: number, weight: number) {
// 集成父类的所有属性
super(name, age);
// 定义子类特有的属性
this.weight = weight;
}
// 定义方法
sayHello() {
// 调用父类的方法
super.sayHello();
}
};
const dog = new Dog("汪汪", 4, 10);
dog.sayHello(); // 动物在叫

抽象(abstract

  • 将普通类变为抽象类,此时该类无法被用于实例化,只能被当做父类继承
  • 将普通方法变成抽象方法,子类必须对抽象方法进行重写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 父类(抽象)
abstract class Animal {
// 定义属性
...
// 定义抽象方法
abstract sayHello(): void;
}
// 子类
class Dog extends Animal {
// 定义属性
...
// 重写方法
sayHello() {
console.log("汪汪汪!")
}
};
const dog = new Dog("汪汪", 4, 10);
dog.sayHello(); // 汪汪汪

接口

  • 用来定义一个类的结构,应该包含哪些属性和方法
  • 接口也可以当成类型声明(type)来使用
  • 接口可以重复声明,最终将所有同名接口内容合并(同名type只能有一个)
  • 接口中的所有属性都不能有实际的值(与抽象类的不同)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 接口当做类型声明使用
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
}
const obj: myInterface = {
name: "abc",
age: 18,
gender: "male"
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 接口限制类的结构
interface myInter {
name: string;
sayHello(): void;
}
class MyClass implements myInter{
name: string;
constructor(name: string){
this.name = name;
}
sayHello() {
console.log("Hello!")
}
}

属性的封装

  • public:修饰的属性可以在任意位置访问(修改)–默认值
  • private:私有属性,只能在当前类的内部进行访问(修改)
  • protected:属性只能在**当前类和当前类的子类(包括后续所有继承下去的子类)**中调用,无法在实例中访问
  • TS提供了存取器getset供实例对私有属性进行访问(修改)
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
class Person {
public _name: string;
private _age: number;

constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
get age() {
return this._age;
}
set age(value: number) {
if (value >= 0) {
this._age = value;
}
}
}
const person = new Person("小明",18)
console.log(person.age); // 18 本质上调用了get name(),间接读取
person.age = 20; // 本质上调用了set name(),间接修改
console.log(person.age); // 20

// 语法糖
class C{
constructor(public name: string, private age: num){}
}
const c = new C("123", 123)

泛型

  • 在定义函数或者类时,如果类型不明确,可以使用泛型
1
2
3
4
5
6
7
8
9
10
11
12
function fn<T>(a: T) {
return a;
}
let result1 = fn(10); // 不指定泛型,TS自动推断
let result2 = fn<string>("Hello!"); // 指定泛型

// 泛型可以使用多个
function fn2<T, K>(a: T, b: K) {
console.log(b);
return a;
}
fn2<number, string>(123, "Hello")
  • 泛型可以使用接口等进行约束
1
2
3
4
5
6
7
8
9
interface Inter{
length: number;
}
// T extends Inter b表示泛型必须是Inter的实现类
function fn3<T extends Inter>(a: T): number{
return a.length;
}
fn3(123);
fn3({length:10});
  • 类中也可以使用泛型
1
2
3
4
5
6
7
class MyClass<T>{
name: T;
constructor(name: T) {
this.name = name;
}
}
const mc = new MyClass("123")

视频资料:
尚硅谷TypeScript教程