TypeScript 是对 JavaScript 的补充,将 JavaScript 由动态类型、弱类型语言转为静态类型、强类型的语言

简介

TypeScript 由三个部分组成:

  • 类型:为 JavaScript 代码添加类型与类型检查来确保健壮性,进入学习
  • 语法:提前使用新语法或新特性来简化代码,进入学习
  • 工程:最终获得可用的 JavaScript 代码,进入学习

环境

npm i typescript ts-node ts-node-dev -g  # 安装 typescript 和 执行工具tsc --init  # 在当前目录生成 typescript 配置文件 tsconfig.jsonts-node index.ts  # 将 typescript 编译成 nodejs 并执行,常用参数有# -P:指定 ts 配置文件位置,默认使用项目下的 tsconfig.json 文件# -T:禁用类型检查# --emit --compilerHost:执行并输出编译后的文件在 .ts-node 文件夹下ts-node-dev index.ts  # 监听文件改变并自动执行# --respawn:启用监听重启# --transpile-only```:禁用类型检查,更快的编译速度

原始类型

const nam: string = 'zsg'const bol: boolean = falseconst age: number = 18const bigint: bigint = 222222222nconst undef: undefined = undefinedconst nul: null = nullconst symbol: symbol = Symbol('hell')const obj: object = {}

null 和 undefined

在 JavaScript 中 null 表示这里有值,但是个空值, undefined 表示这里没有值
在 TypeScript 中没有开启 strictNullChecks 检查的情况下 null 和 undefined 会被视作其他类型的子类型

const str: string = nullconst num: number = undefinedconst nul: undefined = nullconst undef: null = undefined

void

void 在 JavaScript 中表示执行后面的表达式或括号中的表达式并返回 undefined
void 在 TypesScript 中用于描述一个没有 return 任何值的函数的返回值,undefined 能够赋值给 void

const s: void = undefinedfunction f():void { }

数组的类型注解

有两种方式声明一个数组

const arr1: string[] = ['a', 'b']const arr2: Array = [3, 4]

对于定长的数组,使用 Tuple 类型,越界访问就会报错

const arr3: [string, string, number] = ['a', 'b', 4]

为数组的设置可选成员,可选成员值默认为 undefined

const arr4: [string, string?, number?] = ['a', undefined]

使用具名元组

const arr5: [name: string, age: number, sex?:boolean] = ['z', 10]

对象的类型注解

使用 interface 声明一个接口结构,使用这个结构作为对象的注解

interface People {    name: string,    age: number,    sex: boolean}const obj1: People = {    name: 'z',    age: 10,    sex: true}

可选属性和只读属性

interface People {    name: string,    readonly age: number,    sex?: boolean}const obj2: People = {    name: 'z',    age: 10}

Object 和 object

Object 包含了所有的类型,object 包含所有非原始类型的类型即数组,对象,函数

const s1: Object = 12const s2: Object = []const s3: object = {}const s4: object = []const s5: object = () => {}

字面量类型和联合类型

字面量类型主要包括字符串字面量,数字字面量,布尔字面量,对象字面量,他们可以直接作为类型标注

const str1: 9 = 9

联合类型是一组类型的可用集合

const str2: 9 | 'a' | true = truetype users = {bol: true, aaa: string} | {bol: false, bbb: string}  // 创建类型别名const user: users = {  // 实现互斥属性    bol: false,    bbb: 'a'}

枚举

数字枚举默认从 0 开始,以 1 递增,数字枚举是可以双向映射的,而字符串枚举是单向的

enum Items1 {    name = 'zsg',    age = 1,    sex}console.log(Items1.name, Items1.age, Items1.sex, Items1[1])  // zsg 1 2 age

常量枚举,只能通过枚举成员访问枚举值,不能反向访问

const enum Items2 {    name = 'zsg',    age = 1,    sex}

函数

function fun1(name: string): number{    return name.length}const fun2: (name: string) => number = function(name) {    return name.length}type Fun1 = (name: string) => number  // 使用别名const fun3: Fun1 = name => name.lengthinterface Fun2 {  // 使用接口    (name: string): number}const fun4: Fun2 = name => name.lengthfunction fun5(): void{ }  // 函数没有返回值就是 void 类型

函数参数

function fun1(name: string, age?: number): void { }  // 可选参数,默认为 undefinedfunction fun2(name: string, age: number=12): void { }  // 可选参数,并设置了默认值function fun3(name: string, ...rest: string[]): void{ }  // rest 参数为一个数组

函数重载,实现与入参关联的返回值类型,最后是函数的实现需包含所有可能情况

function fun1(name: string): stringfunction fun1(name: number): numberfunction fun1(name: string | number): number | string {    return name}

Class 类

class Foo{    public name: string  // 此类成员在类/类的实例/子类中都能被访问    readonly version = "1.0.1"  // 只读成员    static size = "1024G"  // 静态成员    constructor(name: string) {        this.name = name    }    log(text: string): void {        this._name = text    }    protected get _name(): string {  // 此类成员只能在类与子类中被访问        return this.name + '!'    }    private set _name(v: string) {  // 此类成员仅能在类的内部被访问        this.name = v    }}

在构造函数中的参数加上访问性修饰符即可自动赋值

class Foo{    constructor(public name: string, private age: number) { }}

继承中使用 override 覆盖基类中原有的属性或方法,若基类不存在会报错

class Foo { name = 1 }class Boo extends Foo{    override name = 2}

使用抽象类

abstract class Boo{    abstract name: string    abstract log(text: string): string}class Foo implements Boo{    name = 'zzz'    log(text: string) {        return 'zzz'    }}

使用接口 interface

interface Boo{    // new(): Foo  类似于描述函数的方式      name: string    log(text: string): string}class Foo implements Boo{    name = 'zzz'    log(text: string) {        return 'zzz'    }}

面向对象的五项基本原则

  • S 单一功能原则:一个类应该仅具有一种职责
  • O 开放封闭原则:一个类应该是可扩展但不可修改的
  • L 里式替换原则:一个派生类可以在程序的任何一处对其基类进行替换
  • I 接口分离原则:类的实现方应当只需要实现自己需要的那部分接口
  • D 依赖倒置原则:对功能的实现应该依赖于抽象层

any,unknown,never

any 类型

  • TypeScript 提供了的内置类型 any,来表示接收任意类型
  • 只声明未提供初始值的变量和不为函数参数提供类型标注时,都将被隐式推导为 any
  • 当启用了 noImplicitAny 时,不为函数参数提供类型标注时会报错
  • 它可以在声明后再次接收任意类型,同时可以赋值给任意类型的变量
let bol: any = truebol = 1let str: string = bollet arr: any[] = [1, true, 'a']function fun(a, b) {}

unknown 类型

  • unknown 表示任意类型,且可以再次赋值为任意类型
  • 只能赋值给 any 和 unknown 类型
let unk: unknown = trueunk = 1let b: any = unk

never 类型是空类型,不携带任何类型信息,描述根本不存在的类型

type sn = string & number  // neverfunction aa(): never {    throw new Error()}

类型断言

类型断言能够显式告知类型检查程序当前这个变量的类型,其实就是一个将变量的已有类型更改为新指定的类型

let unk: unknown = { name: 'zzz' }console.log((unk as {name: string}).name, (unk).name)

使用双重断言

let str: string = 'zz'console.log((str as unknown as {name: string}).name)

使用非空断言,使用 ! 和可选链 ? 的用法类似,表示前面的生命一定非空,即排除了 null 和 undefined 类型

let str: {func?: () => number|null} = {    func: () => null}console.log(str.func!()!.toFixed)console.log(str.func?.()?.toFixed)

实现部分接口

interface a{    name1: string,    age: number}const b = {    name1: 'aa'}