ts笔记-类型系统

在ts中,类型系统被设计为可选的,因此可以认为js就是没有类型声明的ts。

类型注解使用 :TypeAnnotation 语法

原始类型

let num: number;
let str: string;
let bool: boolean;

:number:string:boolean都是原始类型

数组

原始类型和[]结合,就是数组类型,如:number[]:string[]:boolean[]

let boolArray: boolean[];

boolArray = [true, false];

let strArray: string[];
strArray = ['1', '2'];


let numArray: number[];
numArray = [1,2]

内联类型

内联类型和数组类型有点像,数组是:typeAnnotation[],内联是:{ /* Structure */}

let name: {
  first: string;
  second: string;
};

name = {
  first: 'John',
  second: 'Doe'
};

内联类型能为我们快速提供类型注释。如果需要多次使用相同的内联注解时,可以使用下面要说的接口。

接口

接口是ts类型系统的核心,这里先做简单介绍。接口可以认为是把多个类型合并为一个新的类型。


interface name {
  first: string;
  second: string;
}

let name1:name = {
  first: 'a',
  second: 'b'
}

let name2:name = {
  first: 'aa',
  second: 'bb'
}

特殊类型

特殊类型包括anynullundefined 以及 void

当我们把类型定义为any,等同于关闭了ts类型检查,因此任何类型都能赋予给他。在把js迁移到ts的时候,经常会使用到他。但过多的使用any就失去了类型检查的意义,因此应该减少使用。

let power: any;

// 赋值任意类型
power = '123';
power = 123;

除了any类型,null和undefined也可以赋值给任意类型

// "strictNullChecks": false, 该值默认为true

let num: number;
let str: string;

// 这些类型能被赋予
num = null;
str = undefined;

void类型

:void表示函数没有返回值,但是函数的默认返回值是undefined,因此void类型只能被赋值为undefined。

function log(message: string): void {
  console.log(message);
}

泛型

在说泛型前,让我们先看一个实际的场景:假设有个函数,它接收一个列表,并且返回这个列表的反向排序。

function reverse(items) {
  const toreturn = [];
  for (let i = items.length - 1; i >= 0; i--) {
    toreturn.push(items[i]);
  }
  return toreturn;
}


let reversed = reverse([1,2,3]); // [3,2,1]

let reversed1 = reverse(['1', '2', '3']); // ['3', '2', '1']

如果没有泛型,为上面的函数添加类型就比较困难(当然也可以用联合类型),因为输入的列表项可能是字符串、数字或者其他类型。使用泛型可以轻松解决。

function reverse<T>(items: T[]): T[] {
  const toreturn = [];
  for (let i = items.length - 1; i >= 0; i--) {
    toreturn.push(items[i]);
  }
  return toreturn;
}

泛型用<T>表示,T可以是任意字符。reverse函数接受类型为T的数组,数组的每一项类型为T,数组的返回值类型为T。当我们传入[1, 2, 3] 时,TypeScript 能推断出 reverse 为 number[] 类型,从而能给你类型安全。与此相似,传入['1', '2', '3'] 时,TypeScript 能推断 reverse 为 string[] 类型

联合类型

联合类型用|表示,顾名思义,他可以表示多种不同的类型。

function formatCommandline(command: string[] | string) {
  let line = '';
  if (typeof command === 'string') {
    line = command.trim();
  } else {
    line = command.join(' ').trim();
  }
}

上面的函数即可以接收数组也可以接收字符串。

交叉类型

交叉类型是将多个类型合并为一个类型,支持所有的类型。交叉类型用&表示,A & B 表示同时包含 A 和 B 的结果

interface Admin {
  id: number,
  administrator: string,
  timestamp: string
}

interface User {
  id: number,
  groups: number[],
  createLog: (id: number) => void,
  timestamp: number
}

let t: Admin & User

t!.administrator // 合法 Admin.administrator: string
t!.groups        // 合法 User.groups: number[]
t!.id            // 合法 id: number
t!.timestamp     // 合法 timestamp: never,never表示不允许被赋值

交叉类型 Admin & User 包含了原类型的所有属性,但是要注意两个接口都拥有 id 和 timestamp 属性,且 id 类型相同,timestamp 类型不同。在此交叉类型中,timestamp 属性类型冲突,不可被赋值。

一个实际的使用场景,mixins函数


function extend<T, U>(first: T, second: U): T & U {
  for(const key in second) {
    (first as T & U)[key] = second[key] as any
  }
  return first as T & U
}

var x = extend({ a: 'hello' }, { b: 42 });

元组类型

元组类型用于约束数组中的子项,使用:[typeofmember1, typeofmember2]表示

const nameAndNumber: [string, number];

nameAndNumber = ['wmui', 18]

类型别名

类型别名可以让我们给类型起一个别名,在联合类型和交叉类型中比较实用,使用type SomeName = someValidTypeAnnotation来创建

type text = string | { text: string };
type coordinates = [number, number];
type callback = (data: string) => void;
posted @ 2021-10-12 17:47  wmui  阅读(205)  评论(0编辑  收藏  举报