基本使用

Mr.ZhaoAbout 5 min

1. 类型声明

  • 类型声明是TS非常重要的一个特点
  • 通过类型声明可以指定TS中变量(参数、形参)的类型
  • 指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
  • 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值

语法:

let 变量: 类型;

let 变量: 类型 =;

2. 自动类型推断

TS拥有自动的类型推断机制,当对变量的声明和赋值是同时进行的,TS编译器会自动推断变量的类型,所以如果你的变量的声明和赋值时同时进行的,可以省略掉类型声明

3. 类型断言

有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式:

  • 第一种

    // 变量 as 类型
    let s: string;
    let f: unknown;
    s = f as string;
    
  • 第二种

    // <类型>变量
    let s: string;
    let f: unknown;
    s = <string>f;
    

4. 基础数据类型和联合类型

1. 基础数据类型

  • number

    let decimal: number = 6;
    let hex: number = 0xf00d;
    let binary: number = 0b1010;
    let octal: number = 0o744;
    let big: bigint = 100n;
    
    // 声明一个变量a,同时指定它的类型为number
    let a: number;
    // a的类型设置为了number,在以后的使用过程中a的值只能是数字
    a = 10;
    a = 'hello'; //代码会报错,因为变量a的类型是number,不能赋值字符串
    
  • boolean

    let isDone: boolean = false;
    
  • string

    let b: string;
    b = 'hello';
    b = 123; //报错
    
  • null

    let nu: null = null;
    
  • undefined

    let un: undefined = undefined;
    

2. 联合类型

联合类型表示取值可以为多种类型中的一种

联合类型使用 | 分隔每个类型

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法

5. 数组

语法:

// 第一种
类型[]
// 第二种
Array<类型>

例:

// string[] 表示字符串数组
let e:string[];
e = ['a', 'b', 'c'];

// number[] 表示数值数组
let f: number[];
f = [1, 2, 3, 4];

let g: Array<number>;
g = [1, 2, 3];

6. 元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象

语法:

let 变量: [类型1, 类型2, 类型3?];

注意:可以使用?来表示可选的值

例:

let h: [string, string];
h = ['hello', 'abc'];

7. 枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等

枚举使用 enum 关键字来定义:

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true

console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true

8. 函数

function MyFn(a = 10,b: 类型,c?: 类型,...rest:数组类型):返回值类型{
    return c;
}

注意:

  • 可以使用默认参数

  • ?表示可选的值,可选参数要在必选参数后面

  • 剩余参数是数组类型

9. 接口

使用接口来定义对象的类型

interface Obj{
    name: string,
    age: number,
};

const obj: Obj = {
    name: 'a',
    age: 10,
};

10. 类型别名

类型别名用来给一个类型起个新名字

type MyUserName = string | number;
// 原来的写法
let a: string | number = 10;
// 使用类型别名
let a: MyUserName = 'abc';

11. 泛型

定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用

举个例子:

function test(arg: any): any{
    return arg;
}

上例中,test函数有一个参数类型不确定,但是能确定的时其返回值的类型和参数的类型是相同的,由于类型不确定所以参数和返回值均使用了any,但是很明显这样做是不合适的,首先使用any会关闭TS的类型检查,其次这样设置也不能体现出参数和返回值是相同的类型

使用泛型:

function test<T>(arg: T): T{
    return arg;
}

这里的<T>就是泛型,T是我们给这个类型起的名字(不一定非叫T),设置泛型后即可在函数中使用T来表示该类型

所以泛型其实很好理解,就表示某个类型

那么如何使用上边的函数呢?

  • 方式一(直接使用):

    使用时可以直接传递参数使用,类型会由TS自动推断出来,但有时编译器无法自动推断时还需要使用下面的方式

    test(10);
    
  • 方式二(指定类型):

    可以在函数后手动指定泛型

    test<number>(10);
    

可以同时指定多个泛型,泛型间使用逗号隔开:

function test<T, K>(a: T, b: K): K{
    return b;
}

test<number, string>(10, "hello");

使用泛型时,完全可以将泛型当成是一个普通的类去使用

类中同样可以使用泛型:

class MyClass<T>{
    prop: T;
    constructor(prop: T){
        this.prop = prop;
    }
}

除此之外,也可以对泛型的范围进行约束

interface MyInter{
    length: number;
};

function test<T extends MyInter>(arg: T): number{
    return arg.length;
}

使用T extends MyInter表示泛型T必须是MyInter的子类,不一定非要使用接口,类和抽象类同样适用