参考
https://ts.xcatliu.com/#%E5%85%B3%E4%BA%8E%E6%9C%AC%E4%B9%A6
终端运行 TS 文件
yarn global add typescriptyarn global add ts-node
文件结构
1 | run-ts |
test.ts
1 | let anyThing: any = "hello"; |
tsconfig.json
1 | { |
类型
回顾 js 数据类型
- 对象类型
- 原始数据类型:布尔值,数字,字符串,null,undefined,symbol
void
- 没有返回值的函数
- 声明一个
void类型的变量没有什么用,因为你只能将它赋值为undefined和nulllet unusable: void = undefined;
undefined 和 null 是所有类型的子类型
可以赋值给任意类型
1 | let num: number = undefined; |
any
在任意值上可以访问任何属性
也允许调用任何方法(存疑,见代码)
1 | let anyThing: any = "hello"; |
应用于 Vue+ts
1 | this.$refs["adSpace"].validate(); // Property 'validate' does not exist on type 'Vue | Element | (Vue | Element)[]'. |
联合类型
eg: let myFavoriteNumber: string | number
只能访问共有的属性或方法
1 | function getLength(something: string | number): number { |
接口
可选、只读、任意属性
1 | interface Person { |
ts 如何判断实例是否实现了接口
不能用 instanceof,因为运行时是不存在 Interface,只能基于接口形状进行判断
数组
1 | let a: [number, string, any] = [3, "7", undefined]; |
类型断言
手动指定一个值的类型, <type>value 或 value as type
tsx 中只能用 value as type,建议统一用 value as type
- 将一个联合类型断言为其中一个类型
- 将一个父类断言为更加具体的子类
- 将一个子类断言为父类
- 将任何一个类型断言为 any
- 将 any 断言为一个具体的类型
断言的限制条件
我们注意到,父子类可以互相断言,any 和其他类型可以互相断言
在 typescript 中,父类兼容子类,比如 Cat extends Animal 即 Animal 兼容 Cat
A 和 B 互相断言的前提:A 兼容 B 或者 B 兼容 A
1 | // 将一个联合类型断言为其中一个类型 |
将子类实例可赋给父类变量
1 | interface Animal { |
赋值时尽量避免用类型断言
我们通过断言 animal as Cat 成功赋值给变量 cat,使 cat 在后续中被当为 Cat 类型,但很明显此时的 cat 是不完整的
1 | import { Animal, Cat } from ""; |
声明文件
引用第三方库时,比如 jQuery,由于 ts 无法识别 $('#foo') 或 jQuery('#foo'),此时需要对 $ 或 jQuery 这两个全局变量进行声明,书写声明文件(.d.ts 为后缀)
管理、下载第三方库声明文件
- 使用
@types统一管理第三方库的声明文件 - 下载 @types 管理下的 jQuery 声明文件 :
npm install @types/jquery --save-dev- 其他第三方库声明文件 https://www.npmjs.com/search?q=@types
- 当一个第三方库没有提供声明文件时,我们就需要自己书写声明文件了
书写、发布声明文件
https://ts.xcatliu.com/basics/declaration-files
内置对象
ts 包含 js、DOM、BOM 的内置对象
很多 js、DOM、BOM 的内置对象,ts 已经在其核心库中定义了,我们可以直接在 ts 中使用这些类型如 Document、HTMLElement、Event、NodeList、Boolean、Error、Date、RegExp 等
ts 不包含 Node.js 的内置对象
如果想用 TypeScript 写 Node.js,则需要引入第三方声明文件:npm install @types/node --save-dev
TypeScript 核心库的定义文件
https://github.com/Microsoft/TypeScript/tree/master/src/lib
类型别名
1 | type Name = string; |
字符串字面量类型
用来约束变量的取值只能是几个字符串之一,也用 type 来定义
type EventNames = 'click' | 'scroll' | 'mousemove'
元组
1 | let tom: [string, number]; |
枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等
1 | enum Days { |
手动赋值(不推荐)
1 | // 未手动赋值的,序号递增,步长为1 |
常数枚举 const enum
常数枚举是使用 const enum 定义的枚举类型
1 | // 常数枚举不允许有计算成员 |
外部枚举 declare enum
常用于声明文件,在编译结果中也会被删除(节省空间吧)
类
相关概念
- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
用法
ES6
继承
super 关键字调用父类的构造函数和方法
1 | class Cat extends Animal { |
getter setter
1 | class Animal { |
静态方法 static
直接通过类名来调用
1 | class Animal { |
访问修饰符
public private protected
访问修饰符,决定了属性、方法能否被访问,分三种 **公有、私有、子类中可访问 **
- public 到处都可访问。属性、方法默认为 public
- private 私有,不能在 声明它的类 的外部访问
- protected 可以在子类中访问
修饰构造函数
- private constructor 不允许继承和实例化
- protected constructor 只允许继承
修饰构造函数参数
相当于 定义且赋值参数
1 | class Animal { |
readonly
readonly 也是访问修饰符,跟 public 三者在一起时要放后面,如 public ``readonly
抽象类
- abstract class 用于继承,且子类必须实现 abstract class 中的 abstract function
类与接口
类实现接口
类的一些共同特性可抽出来作为接口,让所有类来 implement (实现),一个类可实现多个接口
1 | interface Alarm { |
接口继承接口
1 | interface Alarm { |
接口继承类
不常用,此处不赘述
泛型
定义函数、接口、类的时候,不预先指定类型,使用时再指定类型的一种特性
1 | function createArray<T>(length: number, value: T): Array<T> { |
多个类型参数
1 | function swap<T, U>(tuple: [T, U]): [U, T] { |