Typescript

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// js写法
let isBoolean = true;
let name = "zhangsan";
let age = 26;
let undef = undefined;
let n = null;
let stringArr = ["aaa", "bbb"];
// ts写法
let isBoolean: boolean = true;
let name: string = "zhangsan";
let age: number = 26;
let undef: undefined = undefined;
let n: null = null;
//两种形式都是可以表示预设类型为数组里面值类型为string
let stringArr: string[] = ["aaa", "bbb"];
let stringArr: Array<string> = ["aaa", "bbb"];
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
interface infClass={
a:string,
b?:number,
readonly c:boolean,
}
let infObject:infClass={
a:'1',
b:2,
c:false,
}

const 和 readonly 的区别

const 是在运行阶段进行检测,同时 const 如果定义的是复杂数据类型,可以更改地址里面的值但是不能改变引用的地址
readonly 实在编译阶段进行检测,他编译时如果发现对只读属性值的任何更改操作都会直接报错。

不清楚的类型

1
2
3
4
5
6
7
8
9
//看名字是number类型实际上鬼知道他是什么类型
let numberA: any = {
    a: "1",
};
//需要注意any是绕过了所有的类型检查所以any类型可以被赋值给其他非any类型

let a: string = "类型检查";
let b: any = 0;
a = b; //b虽然不是string类型但是可以被赋值给a,因为any会绕过所有的类型检查

没有返回的函数

1
2
3
function setNumber(nunber: Number): void {
    let a = number;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 尖括号形式声明
let anyValue: any = "hello word";
let anyLength: number = (<string>anyValue).length;

// as声明
let anyValue: any = "hello word";
let anyLength: number = (anyValue as string).length;

// 肯定化保证
let score: number;
startClass();
console.log(5 * score);

function startClass() {
    score = 5;
}
let score!: number; // 告知编辑器,运行时会被赋值的
 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
interface Teacher {
    name: string;
    courses: string[];
    score: number;
}
interface Student {
    name: string;
    startTime: Date;
    score: string;
}

type Class = Teacher | Student;

// in - 是否包含某种属性
function startCourse(cls: Class) {
    //判断参数是那种类型
    if ("courses" in cls) {
        // 处理老师类型逻辑
    }
    if ("startTime" in cls) {
        // 处理学生类型逻辑
    }
}

// typeof / instanceof - 类型分类场景下的身份确认
function startCourse(cls: Class) {
    if (typeof cls.score === "number") {
        // 处理老师类型逻辑
    }
    if (typeof cls.score === "string") {
        // 处理学生类型逻辑
    }
}

function startCourse(cls: Class) {
    if (cls instanceof Teacher) {
        // 处理学生类型逻辑
    }
    if (cls instanceof Student) {
        // 处理学生类型逻辑
    }
}
// 自定义类型
const isTeacher = function (cls: Teacher | Student): cls is Teacher {
    // 通过返回值判断是否是老师还是学生
};

const getInfo = (cls: Teacher | Student) => {
    if (isTeacher(cls)) {
        //如果是老师就返回老师的信息
        return cls.courses;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
//重点关注的是传入参数不同
function start(name: number, score: number): number;
function start(name: string, score: string): string;
function start(name: string, score: number): number;
function start(name: Comnbinable, score: Comnbinable) {
    //通过类型守卫进行不同的处理
    //同时如果传入参数类型不在重载的函数列表中,ts会编译报错
    if (typeof name === "number" || typeof score === "number") {
        // 处理
    }
    if (typeof name === "string" || typeof score === "string") {
        // 处理
    }
    if (typeof name === "string" || typeof score === "number") {
        // 处理
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//注意,自由度越高后期维护成度越大,所以泛型和any一样慎用,用的太多会被人打的
function startClass<T, U>(name: T, score: U): T {
    //此函数入参name要和返回参数类型一直,不然会报错
    // 逻辑
}
function startClass<T, U>(name: T, score: U): string {
    // 逻辑
}
function startClass<T, U>(name: T, score: T): T {
    //断言
    return (name + score) as T;
}
 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
//定义一个校长装饰器
function principal(target: Function): void {
    //给老师类额外增加监督老师的功能
    target.prototype.supervise = function (): void {
        // 逻辑
    };
}
//相当于把整个tercher当做参数传递进了装饰器principal
@principal
class tercher {
    constructor() {
        // 业务逻辑
    }
}

// 属性/方法装饰器
function isPrincipal(target: any, key: string): void {
    //对传进来的参数进行数据劫持
    Object.defineProperty(target, key, {});
}

class tercher {
    constructor() {
        // 业务逻辑
    }

    @isPrincipal
    //劫持
    public name: string;
}