title: TypeScript
date: 2020-07-17 21:56:45
tags:
- TypeScript
categories:
- TypeScript
TypeScript
-
TypeScript类型(没有定义object类型!!!)
- number 定义:let a:number = 123;
- boolean 定义:let a:boolean = true;
- string 定义:let a:string = "123";
- array 定义:let arr:number[] = [1]
- tuple 元组类型允许表示一个已知元素数量和类型的数组 定义:let arr1:[number,string] = [1,"123"];
- enum 声明枚举类型和C相同,定义:let arr3:Flag = Flag.success;枚举类型提供的一个便利是你可以由枚举的值得到它的名字string类型。
- any :类似于直接写JS(变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型)
- null :是其他类型的子类型(除never)
- undefined :是其他类型的子类型(除never)
- void :定义空的函数返回值
- never :是一种其他所有类型的子类型但是没有值 只代表从不会出现的值,永远不会到达的值
- function 定义:function abc():returnType {}
- object类型(不同于Object):object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。
-
定义函数
- 必须严格定义参数
- 可选参数:形参变量名后加?代表此参数可选,限制:A required(普通的) parameter cannot follow an optional parameter.。
- 默认参数在类型后加=值,和可选参数搭配挺好用的,function defaultParam(extra?:number,normal:number = 50)
- 剩余参数在变量前写...类型写数组,限制:A rest parameter must be last in a parameter list.放前面后面都别活了。
- TS的函数重载(因为要兼容所以和java有点不同)为了兼容也是有点无奈本质就只是检验一下实参类型 真正不同逻辑还是要自己判断。用重载签名来限制参数类型,用实现签名实现所有重载签名。
//重载签名 function getInfo(score:number):number; function getInfo(score:string):string; //实现签名 function getInfo(score:number|string):any { if(typeof score === "number") { console.log("number"); }else{ console.log("string"); } } getInfo("123"); getInfo(123);
- 箭头函数和ES6相同但是要带类型
-
一些基础知识补足
- 类型推断: 如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
- 联合类型(|):当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法
- 函数的重载:TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。
- 多态:TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。然而,当我们比较带有 private或 protected成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private或 protected成员,那么只有当另外一个类型中也存在这样一个 private或 protected成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected成员也使用这个规则所以其实对于public多态没有必须有继承关系。
- 继承:覆盖的方法并不要求在访问级别上低于父类
- 类型断言:通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。(someValue as string)
-
类和静态方法
- 类中的属性提供了三种修饰符
- public(默认)/protected(不能在类外部访问(只能在本类和子类中及进行访问))/private(只能在类内部访问)
- super关键字:注意:通过 "super" 关键字只能访问基类的公共方法和受保护方法。
- readonly:类变量只读修饰符
- 抽象类和抽象方法,静态和Java相同
- 类中的属性提供了三种修饰符
-
接口
- 描述:TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。 对象字面量会被特殊对待而且会经过 额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。但是如果接口或类为空就不会有这种额外的检查。
interface Point { x: number; y: number; } let p1:Point = {x: 10,y: 20}; console.log(p1);
- 限制类属性接口 : 对对象属性进行约束
- 限制函数接口 : 对函数形参类型和返回值类型进行限制
- 可索引接口 : 对那些能够“通过索引得到”的类型进行约束
- 对类接口 :和Java相似
- 接口扩展 :接口继承接口
-
泛型(战未来)
- 泛型函数
function getData<T>(value:T):T{ return value; }
- 定义泛型类/泛型接口同理
class MinClass<T>{}
- 泛型约束(extends)
- 使用{a:type,b:type}可以约束对象类型
模块(内部叫命名空间外部称为模块)
-
装饰器(注解)
- 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用 @expression这种形式,expression必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。
- 装饰器的写法:普通装饰器(无法传参数),装饰器工厂(可传参)
- 装饰器工厂就是一个简单的函数,它返回一个表达式,以供装饰器在运行时调用。
TypeScript02(官网)
-
基本类型
- void
- void 类型的变量只能赋值为 undefined 和 null,其他类型不能赋值给 void 类型的变量。
- null和undefined
- 默认情况下 undefined 和 null 可以赋值给任意类型的值,但当你设置了"strictNullChecks": true时,undefined 和 null 将只能赋值给它们自身和 void 类型
- 默认情况下null和undefined是所有类型的子类型。
- never类型
- never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。
- void
-
Symbol(ES6)
- Symbol全局注册
- Symbol.for("")
- Symbol的几个内置值
- Symbol.Iterator
- Symbol全局注册
-
Iterator和Generator(ES6)
- Iterator
- Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。
- 只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符(也会调用默认的Iterator接口),将其转为数组。
- 每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
- 遍历器对象本质上,就是一个指针对象。
- 默认有Symbol.Iterator的数据结构
- Generator
- Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
- 执行 Generator 函数会返回一个迭代器对象,也就是说,Generator 函数除了状态机,还是一个迭代器对象生成函数。返回的迭代器对象,可以依次遍历 Generator 函数内部的每一个状态。
- yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
- yield * 生成器中调用生成器函数相当于for...of....另一个生成器函数返回的迭代器
- Iterator
-
接口
- 适用
- 函数
- 对象属性(readonly,可选)
- 可索引类型:支持数字索引和字符串索引,数字索引最终会转换为字符串索引(readonly)
- 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。它们也会确保所有属性与其返回值类型相匹配。
- 接口的继承(extends)
- TypeScript的核心原则之一是对值所具有的结构进行类型检查。在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
- 对象字面量会被特殊对待而且会经过额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。(直接使用对象字面量会有额外属性检查,不止有类型兼容性)---我认为的原因是因为你直接传了一个对象字面量就应该严格符合标准,它本身也不用于其他地方不必兼容。
- 一个类实现了一个接口时,只对其实例部分进行类型检查。
- 当接口继承了一个类类型时,它会继承类的成员但不包括其实现。就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。
- 适用
-
函数
- 完整函数类型:(x: number, y: number) => number
- 构造函数类型:new () => A
- 可选参数(?)和默认参数(=)
- 默认参数与可选参数共享参数类型(函数类型中)。
- 剩余参数(...)和函数重载(限制传入类型)
- 为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
- 重载签名要与实现签名兼容
-
泛型
- 为了支持未来可能出现的类型
- 种类
- 泛型函数(在参数列表前写)
- 泛型接口和泛型类
- 类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
- 无法创建泛型枚举和泛型命名空间
- 泛型约束(extends Type)
-
ES6类
- 所有的函数都有一个name属性,该属性保存的是该函数名称的字符串。
- proto 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。
- JS 对象属性描述符(property descriptor)
- class表达式
- 静态属性
- 静态方法
- 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。静态方法可以与非静态方法重名
- 父类的静态方法和属性,可以被子类继承。
- 私有(#xxx)
- 构造函数中new.target,子类继承父类时,new.target会返回子类,可以用于创建一个不能独立使用只能作为继承的类
- 继承
- 在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。
- super作为函数调用时只能在constructor中使用,super内部的this指的是子类的实例,因此super()在这里相当于Father.prototype.constructor.call(this)
- super作为函数调用时,代表父类的构造函数
- super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
- 两条继承链:
- 子类的proto属性,表示构造函数的继承继承静态属性,总是指向父类
- 子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性。
- ES5和ES6中对于继承的不同点
- ES5是先有子类再去继承父类。
- ES6是在父类的基础上来创建子类对象所以子类构造函数要先运行父类的构造函数。
-
TS中的类
- super只能调用父类中除私有的方法外的方法不能调用属性
- readonly(只能声明时赋值或者构造函数中赋值)/public/protected/private
- 类型属性
- 在构造函数形参中直接合并声明和赋值
constructor(public readonly x:number,public y:number){ }
- 可选类属性
- 存取器
- "set" 访问器不能具有返回类型批注
- 抽象类(可以有抽象属性和抽象存取器)
- TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。然而,当我们比较带有 private或 protected成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private成员,那么只有当另外一个类型中也存在这样一个 private成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected成员也使用这个规则。
-
类和接口
- 接口继承接口,类继承类/抽象类(注意重写的权限),类实现接口都很正常
- 接口继承类出现异常
-
枚举(enum)
- 带名字的常量
- const枚举
- 常量枚举只能使用常量枚举表达式,并且不同于常规的枚举,它们在编译阶段会被删除。 常量枚举成员在使用的地方会被内联进来。
- 运行时的枚举
- 数字枚举/字符串枚举
- 枚举常量做类型和枚举作类型(常量的联合类型)
类型推论
- 一般是由值推断类型但也可以在上下文类型中反向推断。
- 类型兼容性
- 如果x要兼容y,那么y至少具有与x相同的属性
- 函数兼容
- 函数参数数量:允许参数少的赋给参数多的类型自然要兼容。
- 函数返回值:子类赋值给父类(协变)
- 对于有重载的函数,源函数的每个重载都要在目标函数上找到对应的函数签名。 这确保了目标函数可以在所有源函数可调用的地方调用。
- 函数参数类型双向协变
- 协变:子类赋值给父类
- 逆变:父类赋值给子类
- 双向协变:既能协变也能逆变
- 枚举
- 数字枚举类型与数字类型兼容,并且数字类型与数字枚举类型兼容。不同枚举类型之间是不兼容的。
- 高级类型
- 交叉类型(&)
- 联合类型(|)
- 自定义类型保护(is):类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。
- typeof类型保护:这些typeof类型保护只有两种形式能被识别: typeof v === "typename"和 typeof v !== "typename", "typename"必须是 "number", "string", "boolean"或 "symbol"。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。
- instanceof类型保护
- 类型别名(type):类型别名不能被 extends和 implements
- 字面量类型(数字/字符串)
- 类型断言(!去除null)
- 可辨识联合类型
- 可选参数和可选属性:使用了 --strictNullChecks,可选参数会被自动地加上 | undefined
- 索引类型
- 映射类型:从旧类型中创建新类型的一种方式(延申一类需求)
- 它的语法与索引签名的语法类型,内部使用了 for .. in([K in keyof T])
- (增减修饰符+/-)
- unknown类型
- 可以接受任何值
- 如果没有类型断言或基于控制流的类型细化则只能赋值给unknown或any类型
- 如果没有类型断言或基于控制流的类型细化则在其上不能做任何操作。
- unknown 与任何其它类型组成的联合类型,都等于 unknown 类型,但只有any例外,unknown与any组成的联合类型等于any)
- never 类型是 unknown 的子类型
- keyof unknown 等于类型 never
- 只能对 unknown 进行等或不等操作,不能进行其它操作
- 使用映射类型时如果遍历的是 unknown 类型,则不会映射任何属性
- 条件类型
- type Type<T> = T extends string ? string : number
- ts模块以及命名空间
- 命名空间(namespace):当我们是在程序内部用于防止全局污染,想把相关的内容都放在一起的时候,使用命名空间(并不推荐使用)
- 模块(module):当我们封装了一个工具或者库,要适用于模块系统中引入使用时,适合使用模块。
- 声明合并(同名命名空间和接口)
TypeScript03
Introduction
-
编译选项
- 默认使用tsc 文件编译,可以加上-w选项代表实时监视
- 可以直接使用tsc代表编译目录下所有的ts文件,-w选项代表实时监视,但必须要求目录下由tsconfig.json配置文件