本
文
摘
要
什么是 TypeScript:
TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发,代码开源于 GitHub 上。
官网:h
特点:
可以在编译阶段就发现大部分错误,这总比在运行时候出错好不显式的定义类型,也能够自动做出类型推论即使 TypeScript 编译报错,也可以生成 JavaScript 文件Google 开发的 Angular 就是使用 TypeScript 编写的TypeScript 拥抱了 ES7 规范,也支持部分 ES8 草案的规范缺点:
有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的东西
短期可能会增加一些开发成本,多写一些类型的定义,长期维护的项目,TypeScript 能够减少其维护成本
安装:
npm install -g typescript以上命令将会安装typescript编译器和可执行程序(tsc),并且添加到环境变量的全局路径中 tsc -v
编译一个 TypeScript 文件:
tsc hello.ts 类型不匹配时,编辑报错,但可以生成js(编辑通过),如果不希望编译通过需要配饰tsconfig.json
发现在hello.ts同一目录下出现一个hello.js文件,这个文件就是ts编译器输出的内容,其中的js代码与编写的ts代码等价。
可用以下命令来运行:
node hello.js若想要把编译与运行结合起来,可使用ts-node模块:
npm install -g ts-node ts-node hello.ts类型:
原始数据类型:boolean、number、string、null、undefined、symbol、void、any
内置对象类型: Boolean Error Date RegExp Math Array
Document HTMLElementDiv Event MouseEvent NodeList
自定义类型:
class | interface
数值、字符串
let a:number=12;
let b:string = bmw’;
布尔值
let isDone: boolean = false;
NewBoolean: boolean = new Boolean(1);返回对象
null undefined 同理
空值
let unusable: void = undefined
function alertName(): void{}
注意:undefined 和 null 是所有类型的子类型,可以赋值给 number 类型的变量,而 void 类型的变量不能赋值给 number 类型的变量
任意值:
any 允许被赋值为任意类型,任何操作都返回任意值
let myFavoriteNumber: any = seven;
myFavoriteNumber = 7;
类型推论
没有明确的指定类型,依照值推断出一个类型。
let aa=12; //number 推论出为number类型
aa=qq;//无法修改
联合类型
取值可以为多种类型中的一种,没列出的不可以
let myFavoriteNumber: string | number;
对象类型:
依赖接口来描述,不给类型可以推论(原始数据类型和内置对象类型都没有object)
接口:
interface Person {
name: string;
age: number;
}
let p:Person={name:xx,age:11}
注意:定义的变量比接口少了一些属性是不允许
可选属性: age?: number;
任意属性: [propName: string]: any; 任意值
注意:必填属性和可选属性都必须是任意属性的子属性
例如:[propName: string]: string 其他属性要是string子属性
只读属性: readonly id: number; 只能创建的时候被赋值
数组:
变量:类型[]:
let arr: number[] = [1, 1, 2, 3, 5];
let arr: any[] = [1, 1, 2, 3, 5];
Array<elemType>: 泛型 后面会单说
let arr: Array<number> = [1, 1, 2, 3, 5];
推荐:类型[ ] 这种方式;不然在tsx里有兼容问题
函数:
一个函数有输入和输出,进行约束,需要把输入和输出都考虑到
function sum(x: number, y: number): number {}
注意:输入多余的(或者少于要求的)参数,是不被允许的
函数表达式:
let mySum = function (x: number, y: number): number {}
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {}
变量:输入类型=>输出类型=function(参数){}
可选参数: function buildName(a: string, b?: string) {}
注意:可选参数在后
参数默认值: lastName: string = ‘Liu
接口中函数的定义:
interface SearchFunc {
(a: string, b: number): boolean;
}
let c: SearchFunc=function() {return true}
c(qq,11)
类型断言Assertion:
绕过编译器的类型推断,手动指定一个值的类型
<类型>值 (<string>something).length
值 as 类型 (something as string).length
注意:类型断言不是类型转换
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用后者,即 值 as 类型。
用途:
将一个联合类型断言为其中一个类型
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === function) {
return true;
}
return false;
}
需要注意的是,类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误:
将一个父类断言为更加具体的子类
class ApiError extends Error { code: number = 0; } class HttpError extends Error { statusCode: number = 200; } function isApiError(error: Error) { if (typeof (error as ApiError).code === number) { return true; } return false; }将任何一个类型断言为 any
但有的时候,我们非常确定这段代码不会出错,比如下面这个例子
window.foo = 1;
(window as any).foo = 1;
它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any
将 any 断言为一个具体的类型
在日常的开发中,我们不可避免地需要处理 any 类型的变量,它们可能是由于第三方库未能定义好自己的类型,也有可能是历史遗留的或其他人编写的烂代码,还可能是受到 TypeScript 类型系统的限制而无法精确定义类型的场景。
遇到 any 类型的变量时,我们可以选择无视它,任由它滋生更多的 any。
我们也可以选择改进它,通过类型断言及时地把 any 断言为精确的类型,亡羊补牢,使我们的代码向着高可维护性的目标发展。
function getCacheData(key: string): any { return (window as any).cache[key]; } interface Cat { name: string; run(): void; } const tom = getCacheData(tom) as Cat; tom.run();声明文件
ts 使用第三方库时,我们需要引用它的声明文件
ts 并不知道 $ 或 jQuery 是什么东西
declare 关键字来定义它的类型,帮助 TypeScript 判断我们传入的参数类型对不对
类型声明放到一个单独的文件中,这就是声明文件jQuery.d.ts
declare var jQuery: (string) => any; jQuery(#div1); declare var jQuery: (string) => any; 用到的文件的开头用「三斜线指令」表示引用了声明文件 /// <reference path="./jQuery.d.ts" /> 安装第三方声明文件 npm install @types/jquery --save-dev 引入第三方方声明文件 import * as jQuery from jquery; import * as $ from jquery; 用到的文件的开头用「三斜线指令」表示引用了声明文件 /// <reference path="./jQuery.d.ts" /> 安装第三方声明文件 npm install @types/jquery --save-dev 引入第三方方声明文件 import * as jQuery from jquery; import * as $ from jquery;内置对象
Boolean、Error、Date、RegExp,Math let b: Boolean = new Boolean(1); 大驼峰 Document、HTMLElement、Event、NodeList let body: HTMLElement = document.body; let allDiv: NodeList = document.querySelectorAll(div);类:
类(Class):定义了一件事物的抽象特点,包含它的属性和方法
对象(Object):类的实例,通过 new 生成
面向对象(OOP)的三大特性:封装、继承、多态
封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
实例属性: 定义在类内部 name = Jack; | public xx:string 定义在构造器内部 | get|set 属性(){}
继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
es6: 使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法
存取器(getter & setter):用以改变属性的读取和赋值行为
es6: 使用 get 属性(){return this._属性} 和 set 属性(val){this._属性=val} 可以改变属性的赋值和读取行为
静态方法: static 方法名(){} 类名.方法()
静态属性: static 定义在类内部 name = Jack; ts实现了但转换到js暂不支持 调用:类名.方法()
访问修饰符(Modifiers):
修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法
public:修饰的属性或方法是公有的,默认所有的属性和方法都是 public 的
private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected 修饰的属性或方法是私有的+子类中允许访问
public name: string; constructor(name: string) sayHi(): void{} p1: Person = new Person接口:
可以用于对象的形状描述,函数的类型描述,类的行为进行抽象
思想:实现(implements)不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现
门是一个类,防盗门是门的子类。防盗门有一个报警器的功能,给防盗门添加一个报警方法。车内,也有报警器的功能,就可以考虑把报警器提取出来,作为一个接口,防盗门和车都去实现它
interface Action{ 定义接口 readonly id: number;//只读属性 name:string; age?:number;可选 [propName: string]: any;//任意属性 eat?():string 可选方法的返回值 }实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口
泛型:
在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
function createArray<T>(length: number, value: T): Array<T> { let result: T[] = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray<string>(3, x); // [x, x, x]上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。
接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:
createArray(3, x); // [x, x, x’]
定义泛型的时候,可以一次定义多个类型参数:
function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]]; } swap([7, seven]); // [seven, 7]泛型约束:
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; }