tsconfig.json 文件配置项的信息
{
"compilerOptions": {
/* Basic Options */
// "incremental": true, //增量编译
// "tsBuildInfoFile": "./", //增量编译文件的存储位置
// "diagnostics", //打印诊断信息
//"target": "es5", //编译后的语言版本
//"module": "commonjs", //生成代码的模块标准
// "outFile": "./", //将多个相互依赖的文件生成一个文件, 可以用在AMD模块中
// "lib": [], //ts需要引用的库,即声明文件,es5默认dom, "Es5","scripthost"
// "allowJs": true, //允许编译JS文件(js、jsx)
// "checkJs": true, //允许在JS文件中报错, 通常跟allowJs一起使
// "outDir": "./", //指定输出目录
// "rootDir": "./", //指定文件输出目录(用于输出)
//composite: true //工程可以被引用并且进行增量编译
//references: [] //依赖的功程
// "declaration": true, //生成声明文件
// "declarationDir": "./d", //声明文件的路径
// "emitDeclarationOnly": true //只生成声明文件
// "declarationMap": true, //生成声明文件的sourceMap
// "sourceMap": true, //生成目标文件的sourceMap
// "inlineSourceMap": true //生成目标文件的 inline sourceMap
// "typeRoots": [], //声明文件目录,默认 node_modules/@types
// "types": [], //声明文件包
// "removeComments": true, //删除注释
// "noEmit": true, //不输出文件
// "noEmitOnError": true //发生错误时不输出文件
// "importHelpers": true, //通过tslib引入helper函数, 文件必须时模块
// "noEmitHelpers": true, //不生成helper函数,需额外安装 ts-helpers
// "downlevelIteration": true, //降级遍历器的实现 (es3/5)
/* Strict Type-Checking Options */
// "strict": true, //开启所有的严格类型检查
// "alwaysStrict": true, //在代码中注入 "use strict"
// "noImplicitAny": true, //不允许隐式的 any 类型
// "strictNullChecks": false, //不允许把null、undefined 赋值给其他类型变量
// "strictFunctionTypes": false, //不允许函数参数的双向协变
// "strictPropertyInitialization": true, //类的实例属性必须初始化
// "strictBindCallApply": true, //严格的bind/call/apply检查
// "noImplicitThis": true, //不允许 this 有隐式的any类型
/* Additional Checks */
// "noUnusedLocals": true, //检查只声明, 未使用的局部变量
// "noUnusedParameters": true, //检查未使用的函数参数
// "noImplicitReturns": true, //每个分支都要有返回值
// "noFallthroughCasesInSwitch": true, //防止switch 语句贯穿
"esModuleInterop": true, //允许 export = 导出, 由import from 导入
// "allowUmdGlobalAccess": true, //允许在模块中访问UMD全局变量
// "moduleResolution": "node", //模块解析策略
// "baseUrl": "./", // 解析非相对模块的基地址
// "paths": { // 路径映射, 相对于 baseUrl
// "jquery": ["node_modules/jquery/dist/jquery.slim.min.js"]
// },
// "rootDirs": ["src", "out"], //将多个目录放在一个虚拟目录下,用于运行时
//"ListEmittedFiles": true // 打印输出文件
//"listFiles": true //打印编译的文件(包括引用的声明文件)
}
}
typescripts 的数据类型
-
boolean
let a: string = true -
number
let b: number = 1 -
string
let c:string = 'hello -
array
let f: Array<number | string > = [1 , '123'] let f2: any[] = [ 1, true, 'hello] -
tuple (元祖)
元祖类型的定义: 有指定的数据类型元素, 不能进行数组越界操作
let d: [boolean, string, number] = [true, 'hello', 1] -
enum (枚举)
枚举类型分为常量枚举 和 普通枚举, 这两个区别是 常量枚举会在编译阶段被删除并且不能包含计算成员 , 若包含则直接报错
enum Gender = { BODY, GIRL } const enum Colors = { YEKKOW, GREEN, BLACK } -
interface (接口)
interface Week{ (response: string): void; name: string; age: number; status: boolean [x: string]: any } -
null 和 undefined
null 和 undefined 是其他类型的子类型, 可以赋值给其他类型 ,如数字类型,但是不可以直接赋值, 如果想赋值的话 以下有两种解决办法
方法一: 通过联合类型 let x: number | null | undefined; 方法二: 在tsconfig.json 文件里面设置 strictNullChecks 为 false, 则不会对这种情况进行检查let x: number = 2 x = null x = undefined -
any
代表类型 是任何类型, 当类型很复杂的情况下可以使用any
-
void
没有任何类型, 当一个函数没有返回值的时候, 则认为他的返回值是 void 类型, 当我们声明一个变量为void 时, 在非严格模式下可以被赋值为undefined 和 null
-
nerver
never是一个不包含值的类型, 拥有void 返回类型的函数能正常运行, 但是拥有never 返回值的类型无法正常返回, 无法终止, 或会抛出异常
类型推论
函数定义的几种方式
* function ab1(x: number, y: number):number { retrun x + y}
* let ab2: (x: numberm y: number) => number
* type ab3: (x:number, y: number) => number
interface ab4 {
(x: number, y: number): number
}
可选参数
当实参的参数数量 小于 形参的参数数量的时候, 我们可以用? 来使用 可选参数, 但是可选参数一定要在必传参数的后面
function print(name: string, age?: number):string {
return name
}
print('hello')
print( 'hello', '2' )
默认参数
如果不传参数则为undefined, 最后面的形参是默认参数 则可以不用传
function print(name: string, age:string= 'methods', url: string='/post'): string {
return name + age + url
}
print('hello', undefined)
print(hello)
剩余参数
剩余参数 和 es6 里面的方法是一样的 通过...来实现的, 剩余参数在所有参的后面
function print(x: number, ...y: number[]): any {
return x + y.reduce( (pre,cur) => pre + cur, 0 )
}
函数重载
函数重载指的是有两个或者两个以上的相同函数名的函数, 参数类型不一样, 给一个函数提供多种类型定义,母的就是将参数约束为number 和 string, 所以最后实现的不是重载,而是遵循前面的声明
let obj: any = {}
function attr(val: string): string;
function attr(val: number): number;
function attr(val: any): void {
if(typeof val === 'string') {
obj.name = val
} else if( typeof val === 'number' ) {
obj.age = val
}
}
attr('zfpx')
attr(9)
attr(true)
类成员
ts 与js 不同的地方是实例的属性必须要有初始值, 或者在函数中被初始化, 通过public 来进行修饰的则不一定需要初始值, 如果要关闭初始值的话, 则需要在tsconfig配置里面将strictPropertyInitialization改为false
class Dog {
name: string;
age: number = 10;
myName: string
constructor(name: string) {
this.name = name
this.myName = name
}
}
修饰符
- public
公有成员, class类 默认为public 类里面 子类 其他任何地方都可以去访问
- protected
受保护成员 只能在类 或者 子类中才能使用, 不能在实例中调用, 如果constructor上有protected,代表这个类不能被实例化, 只能被继承
- private
私有成员 只能在类或者子类中使用, 不能在实例中调用, 只能在class 中调用
- readonly
只读属性, 不能以去修改
- static 静态属性, 只能通过类名来调用
class Father {
public name: string;
protected age: number;
private money: number;
constructor(name:string,age:number,money:number) {//构造函数
this.name=name;
this.age=age;
this.money=money;
}
getName():string {
return this.name;
}
setName(name:string): void{
this.name=name;
}
}
class Child extends Father{
constructor(name:string,age:number,money:number) {
super(name,age,money); //super代表父类的实例, 这里必须要先定义, 否则无法使用this , 原因是这里的super是调用父类的构造函数来初始化Child, 等价于Father.call(this, ...), 也就是绑定相关属性到this之后才能使用
}
desc() {
console.log(`${this.name} ${this.age} ${this.money}`);
}
}
let child = new Child('zfpx',10,1000);
console.log(child.name);
console.log(child.age);
console.log(child.money);
抽象类 ( abstract)
定义: 描述的是一种抽象的概念, 不能被实例化, 只能被继承, 无法创建抽象类的实例, 抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现, 而且必须实现
abstrace class Animal3 {
name: string;
abstract speak()
}
class Cat extends Animal3 {
speak () {
console.log('cat 喵喵猫')
}
}
let cat = new Cat();
cat.speak();
抽象类 vs 接口
> 不同类之间的公有办法和属性 可以抽象成一个接口
> 而抽象类是提供其它类继承的基类, 无法被实例化, 而抽象类中的抽象方法必须在子类中是实现
> 抽象类本身是无法被实例化的, 但是能够实现方法和初始化方法, 但是接口则不行, 接口只能用于描述, 不能提供方法的结过, 也不能为属性进行初始化
> 一个类只能继承一个类或者抽象类, 但是可以实现(implements)多个接口
> 抽象类 也可以提供接口
接口(interface)
定义:
* 接口就是把一些类的公有方法 和属性给抽象出来, 用来约束实现此类的接口
* 一个类可以继承一个类并实现多个接口
* 接口像插件一样可以用来增强类的
* 一个类可以实现多个接口,一个接口也可以被多个类实现, 但是一个类可以多个子类, 但是只能有一个父类
接口的用法
interface Speakable {
speak(): void;
name?: string
readonly id: number
[x: string]: any
}
接口的实现
interface Boy {
name: string,
eat(): void
}
interface Girl {
age: number
}
class Child implements Boy, Girl {
public name:string = 'tom'
public age: number = 10
eat () {
console.log('Person 5 说话')
}
}
接口的继承
interface Father {
speak(): void
}
interface child extends Father {
speakChinese(): void
}
class Person5 implements Child {
speak () {
console.log('Person 5')
}
speakChinese () {
console.log('speakChinese')
}
}
函数类型接口
interface discount {
(price: number): number
}
let cost: discount = function(price: number) :number {
return price * 8
}
构造函数的类型
class Animal{
constructor(public name:string){
}
}
interface WithNameClass{
new(name:string):Animal
}
function createAnimal(clazz:WithNameClass,name:string){
return new clazz(name);
}
let a = createAnimal(Animal,'zhufeng');
console.log(a.name);
类型兼容
当一个类型y 可以被赋值给另一个类型x 的时候我们可以理解为x
类型保护
类型保护其实就是一种表达式, 在它们编译的时候就能通过类型信息, 确保某个作用域内变量的类型, 能够通过关键字判断分支中的类型
关键字 typeof instanceof null in
typeof 用法
function dobule(input: string | number | boolean) {
if( typeof input === string ) {
input.toLowerCase()
} else if(typeof input === 'number') {
input.toFixed(2)
} else {
input
}
}
instanceof 用法
class Animal {
public name: string = 'zhufeng'
}
class Bird extends Animal {
public swing: number = 2
}
function getName(a: Animal) {
if(a instanceof Bird) {
a.swing
} else {
a.name
}
}
null 的用法
function getFirstLetter(s: string | null) {
if( s === null ) {
s = ''
}
return s.chartAt(0)
}
in 的用法
interface Bird {
swing: number
}
interface Dog {
leg: nubmer
}
function getNumber(x: Bird | Dog) {
if ( 'swing' in x ) {
return x.swing
}
return x.leg
}
自定义类型保护
interface Bird {
swing: number
}
interface Dog {
leg: number
}
//没有相同字段可以定义一个类型保护函数
function isBird(x: Bird | Dog): x is Bird {
return x.legs == 2;
}
function getAnimal(x: Bird | Dog) {
if (isBird(x)) {
x.name1;
} else {
}
}
let x: Bird = { name1: 'Bird', legs: 2 };
getAnimal(x);
类型变换
交叉类型
取的是两个类型的并集
interface Body {
name: string
}
interface Girl {
age: number
}
type Child = Body & Girl
let child:Child = {
name: 'tom',
age: 12
}
typeof 获取一个变量
//先定义类型在定义变量
typeof PeoPle = {
name: string;
age: number;
gender: string
}
let p1: People = {
name: '珠峰'
age: 10,
gender: 'male'
}
//先定义变量在定义类型
let p1 = {
name: 'zhufeng',
age: 10,
gender: 'male'
}
type People = typeof p1
function getName(p: People): string {
return p.name
}
[] 索引访问操作符
//可以通过 []获取一个类型的子类型
interface Person {
name: string;
age: number;
job: {
name: string
};
interests: {name: string, level: number}[]
}
let FrontEndJob:Person['job'] = {
name: '前端工程'
}
let interestLevel: Person['interests'][0]['level'] = 2
keyof 索引类型查询操作符
interface Person = {
name: string;
age: nubmer;
gender: 'mode' | 'commonJS'
}
// 等价于下面 type personKey = 'name' | 'age' | 'gender'
type personKey = keyof Person
function getValueByKey(p: Person, key: PersonKey) {
return p[key]
}
let val = getValueByKey({name: 'zhufeng', age: 10, gender: 'male'}, 'name')
内置工具模块
Partial , Required, Pick, Readonly
Partial
// 将必须参数轮询变为可选
//等价于下面 type Partials<T> = { [key in keyof T]? T[key] }
interface A = {
a1: string;
a2: number;
a3: boolean
}
type aPartail = Partail<A>
const a: aPartail = {}
Required
// 将可选参数变为必选参数
// 等价于下面 type Requireds<T> = { [p in keyof T]-?: T[p] }
interface Person {
name: string;
age: number;
gender? "male" | 'female'
let p: Required<Person> = {
name: 'zhufeng',
age: 10,
gender: 'male'
}
}
Pick
// 能过将我们从传入的属性中摘取某一项返回
// 等价于下面 type Pick<T, k extends keyof T> = {[p in K]: T[p]}
interface Animal {
name: string;
age: number
}
type AnimalSub = Pick<Animal, 'name'> // {name: string}
Readonly
// 为传入的每一项属性都加上readonly 修饰符来实现
// 等价于 type Readonly<T> {readonly [p in keyof T]: T[p]}
interface Person {
name: string;
age: number;
gender?: "male" | "female"
}
let p:Readonly<Person> = {
name: 'zhufeng',
age: 10,
gender: 'male'
}
内置条件模块
Exclude<T, U> // 从 T 可分配给的类型中排除 U。
Extract<T, U> // 从 T 可分配的类型中提取 U。
NonNullable // 从 T 中排除 null 和 undefined。
ReturnType // 获取函数类型的返回类型。
InstanceType // 获取构造函数类型的实例类型。
Exclude
type E = Exclude<string|number,string>;
let e:E = 10;
Extract
type E = Extract<string|number,string>;
let e:E = '1';
NonNullable
type E = NonNullable<string|number|null|undefined>;
let e:E = null;
ReturnType
function getUserInfo() {
return { name: "zhufeng", age: 10 };
}
// 通过 ReturnType 将 getUserInfo 的返回值类型赋给了 UserInfo
type UserInfo = ReturnType<typeof getUserInfo>;
const userA: UserInfo = {
name: "zhufeng",
age: 10
};
InstanceType
class Person{
name:string;
constructor(name){
this.name = name;
}
getName(){console.log(this.name)}
}
type P = InstanceType<typeof Person>;
let p:P = {name:'zhufeng',getName(){}};