数组 vs 元组
- 数组
const list1: number[] = [1, 2, 3]; // 方式一(推荐)
const list2: Array<number> = [1, 2, 3]; // 方式二
const list3: (number | string)[] = [1, 3, "2"]; // 使用联合类型声明多种类型
type User = { name: string; age: number }; // 使用类型别名
const list4: User[] = [
{
name: "litianzhen",
age: 20,
},
];
- 元组
const userInfo: [string, string, number] = ["monkey", "tiger", 100];
接口
interface Person {
readonly firstName: string // readonly 只读属性
lastName: string
age?: number // 可选属性
say(): string // 方法
[prop: string]: // 索引签名 -> 绕开多余属性
}
function getFullName({firstName, lastName}: Arg) {
return `${firstName} ${lastName}`
}
implements
interface Vegetables {
color?: string;
type: string;
}
class tomato implements Vegetables {
color = "red";
type = "vegetable"; // 必须声明type
}
extends
interface Tomato extends Vegetables {
eat(): string;
}
定义函数类型
interface AddFunc {
(num1: number, num2: number): number;
}
const add: AddFunc = (num1, num2) => num1 + num2;
Class
修饰符
class Person {
public name: string;
protected sex: string;
private age = 20;
sayHello() {
console.log("hello");
}
constructor(name: string, sex: string) {
this.name = name;
this.sex = sex;
}
}
class Student extends Person {
constructor(name: string, sex: string) {
super(name, sex);
}
getSex() {
return this.sex; // 子类继承中可以使用
}
}
const p = new Person("tianzhen", "man");
console.log(p.sayHello());
console.log(p.name);
console.log(p.sex); // 不可访问
console.log(p.age); // 不可访问
const s = new Student("hongli", "woman");
console.log(s.name);
console.log(s.getSex());
- 如果没有使用修饰符,默认为public
- private只能在自己类的内部使用
- protected可以在被继承的子类中使用
简化写法
class Teacher {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Teacher {
constructor(public name: string) {}
}
const t = new Teacher("litianzhen teacher");
console.log(t.name);
上面两种写法是等价的
getter/setter
class Student {
constructor(private _name: string) {}
get name() {
return this._name;
}
set name(name) {
this._name = "hello " + name;
}
}
const stu = new Student("tianzhen");
console.log(stu.name);
stu.name = "hongli";
console.log(stu.name);
当不想暴露一些私有属性时,可使用private并提供get/set
单例
class Demo {
private constructor(public name: string) {}
private static instance: Demo;
static getInstance(name: string) {
if (!this.instance) {
this.instance = new Demo(name);
}
return this.instance;
}
}
const demo1 = Demo.getInstance("tianzhen");
const demo2 = Demo.getInstance("tianzhen1"); // 无效,只能实例一次
console.log(demo1.name); // tianzhen
console.log(demo2.name); // tianzhen
console.log(demo1 === demo2); // true
抽象类
- 把类的共性提取出来,然后在抽象类中定义
- 抽象类的抽象方法必须被实现
- 抽象类不能被实例化
abstract class Gemo {
width = 0;
height = 0;
abstract getArea(): number;
}
new Gemo(); // 无法创建抽象类的实例
class Circle extends Gemo {
getArea() {
return 200;
}
}
class Square extends Gemo {
getArea() {
return 200;
}
}
TS补充类型
元组
可以看作是数组的扩展,表示已知元素数量和类型的数组
let tuple: [string, number, boolean];
tuple = ["a", 10, false];
tuple = ["a", 10]; // error
tuple = [10, "a", false]; // error
枚举
给一组数值赋予名字
enum Roles {
SUPER_ADMIN, // 0
ADMIN, // 1
USER, // 2
}
默认从0开始:Roles.ADMIN === 1
enum Roles {
SUPER_ADMIN = 1,
ADMIN = "admin",
USER = 2,
}
也可以赋予不同的值
Any
任意类型
let a: any;
a = 1;
a = false;
a = "ha";
void
没有类型
const log = (value: string): void => {
console.log(value);
};
never
指那些不存在的值类型(异常,死循环)
const errorFun = (message: string): never => {
throw new Error(message);
};
unknown
需配合类型断言来缩小范围
交叉联合类型
- 交叉类型:& 取交集
- 联合类型:| 取并集
泛型
定义函数、接口、类的时候,不预先指定具体的类型,而在使用时再制定类型
const getArray = <T, U>(param1: T, param2: U, times: number): [T, U][] => {
return new Array(times).fill([param1, param2]);
};
getArray<number, string>("tianzhen", 1, 4);
tsconfig.json
- tsc 默认会对根目录所有ts进行编译 ;tsc file 不会使用配置文件
- include: []
- files
- exclude
- noImplicitAny: true 必须显示设置any
- strictNullChecks: true 强制校验null类型
- rootDir
- outDir
- checkJS
- allowJS