Typescript学习总结(一)

247 阅读1分钟

Typescript类型定义

1、Boolean

只能赋值简单的true/false值,在JavaScript和TypeScript里叫做boolean

let isTrue: Boolean = true;
let isFalse: Boolean = false;

2、Nunber

和javascript一样,Typescript里的所有数字都是浮点数。这些浮点数的类型是number,同样也支持二进制八进制十进制十六进制字面量。

let num3: number = 0b110; //二进制
let num4: number = 0o744; //八进制
let num1: number = 6; //十进制
let num2: number = 0xf00d; //十六进制

3、String

字符串的类型为string,跟javascript一样可以使用"'以及反引号。

let str1: string = 'Javascript';
let str2: string = "CSS";
let str3: string = `My favourite Javascript Framework is ${Vue}`;

4、Array

定义数组有两种形式:第一种是在元素类型后面接上[],表示由此类型元素组成的一个数组:

let numberArr: number[] = [1, 2, 3];

第二种是使用数组泛型Array<元素类型>

let stringArr: Array<string | number | boolean> = [666, '厚礼蟹', true];

5、元组Tuple

元组类型表示定义一个已知元素数量和类型的数组,各元素类型不必相同。元素类型或元素数量必须都符合规则。比如:

let tupleArray1: [string, number, boolean] = ['123', 321, false]; √
let tupleArray2: [string, number, boolean] = [321, '123', true]; ×
let tupleArray3: [string, number, boolean] = ['456', 678]; ×

6、枚举enum

定义枚举是用关键字enum,默认情况下,枚举会从0为开始编号。可以手动更改任意枚举元素的编号。

enum Color {
    Red,
    Yellow = 4,
    Blue,
    Pink
}
let color: string = Color[5];
console.log(color); // 'Blue'

也可以为枚举元素赋值字符串

enum Color {
    Yellow = '黄色',
    Red = '红色',
    Black = '黑色'
}
let color: string = Color.Red;
console.log(color); // '红色'

7、Any

Any类型可以接受任何类型的值,在我们编程阶段还不清楚变量的类型时,他是最好的选择。

let notSure: any = 4;
notSure = '字符串也可以';
notSure = true; // Boolean类型也可以

8、Void

Void类型像是与Any类型相反,它表示没有任何类型。当一个函数没有返回值时,通常会用到它:

function warn(): void {
    console.warn('This function does not return any value!');
}

void类型只能接受undefinednull

let u: undefined = undefined;
let n: null = null;

9、Never

Never类型表示的是永不存在的值的类型。例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 即使 any也不可以赋值给never

// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) { }
}

10、Object

Object表示非原始类型,意义与Javascript的Object相同:

function createStudent(student: Object): void {
    console.log(student);
}
createStudent({name: '帅哥', age: 18}); √
createStudent("I'm a student"); ×

11、类型断言

有时候当我们确定某个值的类型时可以使用类型断言。它有两种写法:

第一种是使用尖括号语法:

let str1: string = 'this is a string';
let strLength: number = (<string>str1).length;

第二种是as语法

let str1: string = 'this is a string';
let strLength: number = (str1 as str1).length;

11、unknown

unknown类型和any类型的相同点在于两者都可以接受任意类型的值,不同点在于any可以赋值给除了never类型的变量外的所有类型,而unknown类型不能赋值给其他任意类型。

let value1: unknown;
value1 = true;
value1 = '123';
value1 = 312;
value1 = {name: 'unknown'};

12、接口

接口(interface)可以描述函数、对象、构造器的结构:

对象:

interface PersonInterface {
    name: string;
    age: number;
}

class Person implements PersonInterface {
    name: string;
    age: number;
}

const obj: PersonInterface = {
    name: 'xxx',
    age: 18
}

函数:

interface SayHello {
    (name: string): string;
}

const func: SayHello = (name: string) => {
    return 'hello,' + name
}

构造器:

interface PersonConstructor {
    new (name: string, age: number): IPerson;
}
function createPerson(ctor: PersonConstructor):IPerson {
    return new ctor('guang', 18);
}

对象类型、class类型在Typescript中也叫索引类型,也就是索引了多个元素的类型的意思。当对象需要添加动态属性时,如果不知道是什么属性,可以使用索引签名

interface People {
    sex: 'Male' | 'Female',
    age: number,
    name: string,
    [prop: string]: any;
}
let people1: People = {
    name: '张三',
    age: 3,
    sex: 'Male',
    alias: '法外狂徒',
    stature: 166
}

interface除了描述类型的结构外,还支持描述类型的属性,比如是否只读readonly,是否可选?

interface Student {
    readonly sex: 'Male' | 'Female',
    age?: number;
    name: string;
}

13、条件:extends ? :

Typescript里的条件判断是extends ? :,叫做条件类型,与Javascript中的三元表达式相似。用法如下:

type result = 1 extends 2 ? true : false;
//结果为: 
type result = false;

在上面我们用到了type,在typescript中表示类型定义,也就是定义一个类型。在上面的代码中可以看到类型resultfalse。typesript中支持字面量类型,因此false也可以作为类型。

14、泛型

在上面的案例中可以看出逻辑毫无意义,因为值都是静态的,那么怎么用动态类型去做类型运算呢。答案就是泛型。 上面的例子可以调整为:

type isTwo<T> = T extends 2 ? true : false;
type result1 = isTwo<2>;
type result2 = isTwo<3>;
// 运算结果如下:
type result1 = true;
type result2 = false;

这种类型也叫高级类型

高级类型的特点就是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

15、infer

infer在typescript中的作用是提取类型的一部分。比如提取数组中的第一个元素:

type FirstItem<T extends unknown[]> = T extends [infer First, ...infer R] ? First : never;

type result = FirstItem<[1, 2, 3]>;
//运算结果如下:
type result = 1;

这里的第一个extends并不表示条件判断,条件类型为entends ? :,这里的extends表示约束的意思,也就是约束了类型参数只能是数组类型。

16、联合 |

联合类型(Union)类似 js 里的或运算符 ||,但是作用于类型,代表类型可以是几个类型之一。

type Union = 1 | 2 | 3;

17、交叉 &

交叉类型(Intersection)类似 js 中的与运算符 &&,但是作用于类型,代表对类型做合并。

type ObjType = {a: number } & {c: boolean};
type result = {a: number, c: boolean} extends ObjType ? true : false;
// 运算结果如下:
type result = true;

18、映射类型

映射类型可以在对索引类型做修改时用到:

type MapType<T> = { [Key in keyof T]?: T[Key] }
type result = MapType<{name: string, age: number}>
//运算结果如下:
type result = {
    name?: string,
    age?: number
}

keyof T 是查询索引类型中所有的索引,叫做索引查询

T[Key] 是取索引类型某个索引的值,叫做索引访问

索引可以用as运算符定义别名。叫做重映射

type MapType<T> = {
    [ 
    Key in keyof T
        as `${Key & string}${Key & string}${Key & string}`
    ]: [T[Key], T[Key], T[Key]] 
}

以上对索引做了修改,改成了3个key重复。

以上是学习Typescript后对类型定义的一些总结