认识Typescript
Typescript,也称作ts(后文以ts代替),是js的一个超集,本质上就是为js添加可选的静态类型和基于类的面对对象式编程。 ts运行在编译端,具体的一个工作流程是:ts文件编译成js文件 => js文件合成主js文件 => js运行;如下图: 简而言之,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
联合类型和交叉类型
联合类型
有时候,我们定义一个类型的时候,它既可以是字符串,或者数组,又或者数字等等类型的时候,我们就可以采用联合类型的方式。多个类型,中间用|
隔开,便组成了联合类型
string | number | boolean
交叉类型
在某些情况,我们定义了很多类型或者接口(下面会介绍),函数等,但我们需要一个类型包含我们之前定义等所有类型的情况,即可以使用交叉类型。多个类型用&
拼接
string & number
参考资源
ts中文文档:github.com/zhongsp/Typ…