Typescript入门

659 阅读7分钟

认识Typescript

Typescript,也称作ts(后文以ts代替),是js的一个超集,本质上就是为js添加可选的静态类型和基于类的面对对象式编程。 ts运行在编译端,具体的一个工作流程是:ts文件编译成js文件 => js文件合成主js文件 => js运行;如下图: image.png 简而言之,js是在运行端执行,所以报错会在运行端,而ts端引入,可以在大型项目代码编译的时候就报错,更容易开发者进行错误的一个处理,相比于js打包部署后才会报错的特点,ts展现的代码逻辑错误更加明显

一、TS 基础类型

类型介绍

JS中的基本数据结构在TS中也包含在内,分别是boolean,string,underfine,null,number,symbol TS写法举例:

let name : string = 'lisa'

本质上就是对变量等添加类型,方便编译判断类型是否错误。 除此以外,TS也包含了其他非基本数据类型

数组类型

let list : number[] = [1,2,3]
let list : Array<number> = [1,2,3]  //泛型语法

object、Object

object类型

object表示非原始类,也就是我们常说的new obj后的实例

interface obc{
    get(o : object) : any
 
}

let p = {}

obc.get(p)  //ok
obc.get(true) //error

Object类型

Object表示原始对象类型,也就是我们常说万物皆对象的对象

枚举类型enum

使⽤枚举我们可以定义⼀些带名字的常量。 使⽤枚举可以清晰地表达意图或创建⼀组有区别的⽤例。 TypeScript ⽀持数字的和基于字符串的枚举

enum Direction {
 NORTH,
 SOUTH,
 EAST,
 WEST,
}
let dir: Direction = Direction.NORTH;

默认情况下,NORTH 的初始值为 0,其余的成员会从 1 开始⾃动增⻓。换句话说,Direction.SOUTH 的值为 1,Direction.EAST 的值为 2,Direction.WEST 的值为 3。

Any 类型

TS中任何类型都可以归为any类型,可以说any类型就是TS的一个全局类型,顶级类型

let notSure: any = 666;
notSure = "semlinker";
notSure = false;

tuple 元组类型

元组的概念产生于其他静态语言,比如python等。元组与数组相似但又不同于数组,数组是只能存放同一类型,而元组可以存放不同的类型,对于元组中的每一个属性都必须为其添加类型

let tupleType: [string, boolean];
tupleType = ["semlinker", true];

void类型

void类型是用来定义一个无返回值的函数的类型

// 声明函数返回值为void
function warnUser(): void {
 console.log("This is my warning message")
}

never类型

never类型表示那些永远不存在的值的类型

还有其他的类型(不常见不常用),这里便不做过多介绍,详细可以查看官网

接口 interface

TypeScript 中的接⼝是⼀个⾮常灵活的概念,除了可⽤于对类的⼀部分⾏为进⾏抽象以外,也常⽤于对 「对象的形状(Shape)」进⾏描述,当然也可以用来描述函数类型

interface point{
  name: string
  age: number
 }

可选属性?| 只读属性readonly | 任意属性(通过索引签名实现)

interface point{
  name: string
  age?: number
  readonly sex :number
  [x: string] : any
 }

可索引类型

可索引类型,可通过索引得到的类型,通常具有一个_索引签名_,描述索引属性值的类型,还有相应的索引返回值的类型

interface StringArray {
  [index: number]: string;
}

 let myArray: StringArray;
 myArray = ["Bob", "Fred"];

 let myStr: string = myArray[0];

注意,typescript只支持2种索引签名,字符串和数字。可以同时使用这两种签名,但是数字索引的返回值必须是字符串返回值类型的子类。这是因为,js在通过索引访问值的时候,会先将索引值转换为字符串(隐式调用toString)

实现 implement

实现的意思就是定义一个接口,强制一个类或对象等等去符合这个接口所定义的类型契约

interface ClockInterface {
  currentTime: Date;
}

class Clock implements ClockInterface {
  currentTime: Date = new Date();
  constructor(h: number, m: number) {}
}

注意,这里类实现了接口,接口只描述了类的公共部分,与私有部分无关。(类公有和私有的区别)

继承 extend

与类中即成一样,接口也可以继承,继承的新接口拥有被继承接口的所有属性类型定义,通俗的讲就是复制一个接口中的成员到另一个接口

interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

let square = {} as Square;
square.color = "blue";
square.sideLength = 10;

接口继承类

接口也可以通过extends继承类,相当于拥有了类中到成员,但没有实现,也就是没有进行类型定义;继承包括私有和公有,静态等

函数

ts中函数的类型定义包括输入和输出

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };


let myAdd: (x:number, y:number) => number =
    function(x: number, y: number): number { return x + y; };

可选参数 ? (可选参数必须写在必选参数的最后面)

默认参数 =

剩余参数 ...rest

函数重载

函数重载指的是使用相同名称和不同参数数量创建的统一函数,不会被覆盖而且依旧还会存在并按条件执行,即ts可以出现相同函数名的不同函数,而js中会被覆盖掉
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: Combinable, b: Combinable) {
 // type Combinable = string | number;
 if (typeof a === 'string' || typeof b === 'string') {
 return a.toString() + b.toString();
 }
 return a + b;
}

声明语句

  • declare var 声明全局变量
  • declare function 声明全局方法
  • declare class 声明全局类
  • declare enum 声明全局枚举类型
  • declare namespace 声明(含有子属性的)全局对象
  • interface 和 type 声明全局类型
  • export 导出变量
  • export namespace 导出(含有子属性的)对象
  • export default ES6 默认导出
  • export = 导出模块
  • export as namespace UMD 库声明全局变量
  • declare global 扩展全局变量
  • declare module 扩展模块
  • /// <reference /> 三斜线指令

二、高级类型

泛型

在ts中,对于类型的指定我们可以给其先设定一个变量,等到要用到的时候再给变量设定类型值,以达到可以多次重用赋予不同类型的形式,这个就叫做泛型

function identity<T>(arg: T): T {
    return arg;
}
let output = identity<string>("myString");

如上,T就是泛型变量,当然我们也可以对T进行泛型约束,定义一个接口,让T继承而达到对T的某种条件约束

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

泛型常用工具类型

  • typeof 获取某变量等的类型
  • keyof 获取某类型的所有键,返回的是联合类型
  • in 遍历枚举类型
  • infer 声明一个类型变量并使用
  • Partial 将类型中所有属性变成可选属性
  • Require 将类型中所有属性变成必选属性
  • Pick<T,K extends keyof T> 将T类型中的k子属性挑出来变成其他类型的子属性
  • Record<k extends keyof any,T>将k类型的所有属性的类型设置为T类型
  • Exclude<T,K>将T类型中的属于K类型的移除掉
  • ReturnType获取‘函数T’的类型值

泛型条件约束

这里的条件约束指的是兼容性约束

T extends U ? X : Y

以上的意思是,T能否赋值给U,能则类型是X,不能则是Y

联合类型和交叉类型

联合类型

有时候,我们定义一个类型的时候,它既可以是字符串,或者数组,又或者数字等等类型的时候,我们就可以采用联合类型的方式。多个类型,中间用 隔开,便组成了联合类型

stringnumberboolean

交叉类型

在某些情况,我们定义了很多类型或者接口(下面会介绍),函数等,但我们需要一个类型包含我们之前定义等所有类型的情况,即可以使用交叉类型。多个类型用&拼接

string & number

参考资源

ts中文文档:github.com/zhongsp/Typ…