1.
为什么要学习TypeScript ?
1, 未来趋势,目前来看发展,和应用趋势很快 2, vue3.0发布后,基本就离不开ts了 3, 使用 TypeScript 可以帮助我们防止在编写 JavaScript 代码时因为数据类型的转换造成的意想不到的错误。 提前帮我们发现代码出现错的风险。 4, 团队成员使用 JavaScript 时很容易瞎写,不受规范约束。 但是如果使用TypeScript那大家都不得不遵守规范。 5, TypeScript 紧跟 JavaScript 的发展,ES7 、ES8、ES9 相关语言的新特性都支持,比浏览器支持的速度更快。2.
什么样的项目需要TypeScript ?
1, 团队多人开发的大项目 2, 开源项目 3, 企业对代码有高质量要求的项目 3. TypeScript有那些优点?1, 规避大量低级错误,避免时间浪费,省时
2, 减少多人协作项目的成本,大型项目友好,省力
3, 良好代码提示,不用反复文件跳转或者翻文档,省心
4.
JavaScript 与 TypeScript 的区别
TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。 Language Features 语言特性 -TypeScript 是一种给 JavaScript 添加特性的语言扩展。增加的功能包括:
1.
类型批注和编译时类型检查
类型推断
类型擦除
接口
枚举
Mixin
泛型编程
命名空间
元组
Await
2.
类 (以下功能是从 ECMA 2015 反向移植而来:)
模块
lambda 函数的箭头语法
可选参数以及默认参数
Start using开始使用TypeScript -// 1,安装npm install -g TypeScript// 2,创建环境mkdir ts-demo && cd ts-demo //创建ts-demo目录并且进入目录mkdir src && touch src/index.ts // 创建src目录,并且创建index.ts文件// 3,使用用npm将目录初始化:npm init// 4,初始化typescripttsc --init
上面步骤完成后目录下多了一个 tsconfig.json 文件. 这是ts的配置文件
完整的ts配置:
{ "compilerOptions": { /* Basic Options */ "target": "es5" /* target用于指定编译之后的版本目标: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, "module": "commonjs" /* 用来指定要使用的模块标准: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "lib": ["es6", "dom"] /* lib用于指定要包含在编译中的库文件 */, "allowJs": true, /* allowJs设置的值为true或false,用来指定是否允许编译js文件,默认是false,即不编译js文件 */ "checkJs": true, /* checkJs的值为true或false,用来指定是否检查和报告js文件中的错误,默认是false */ "jsx": "preserve", /* 指定jsx代码用于的开发环境: 'preserve', 'react-native', or 'react'. */ "declaration": true, /* declaration的值为true或false,用来指定是否在编译的时候生成相应的".d.ts"声明文件。如果设为true,编译每个ts文件之后会生成一个js文件和一个声明文件。但是declaration和allowJs不能同时设为true */ "declarationMap": true, /* 值为true或false,指定是否为声明文件.d.ts生成map文件 */ "sourceMap": true, /* sourceMap的值为true或false,用来指定编译时是否生成.map文件 */ "outFile": "./dist/main.js", /* outFile用于指定将输出文件合并为一个文件,它的值为一个文件路径名。比如设置为"./dist/main.js",则输出的文件为一个main.js文件。但是要注意,只有设置module的值为amd和system模块时才支持这个配置 */ "outDir": "./dist", /* outDir用来指定输出文件夹,值为一个文件夹路径字符串,输出的文件都将放置在这个文件夹 */ "rootDir": "./", /* 用来指定编译文件的根目录,编译器会在根目录查找入口文件,如果编译器发现以rootDir的值作为根目录查找入口文件并不会把所有文件加载进去的话会报错,但是不会停止编译 */ "composite": true, /* 是否编译构建引用项目 */ "removeComments": true, /* removeComments的值为true或false,用于指定是否将编译后的文件中的注释删掉,设为true的话即删掉注释,默认为false */ "noEmit": true, /* 不生成编译文件,这个一般比较少用 */ "importHelpers": true, /* importHelpers的值为true或false,指定是否引入tslib里的辅助工具函数,默认为false */ "downlevelIteration": true, /* 当target为'ES5' or 'ES3'时,为'for-of', spread, and destructuring'中的迭代器提供完全支持 */ "isolatedModules": true, /* isolatedModules的值为true或false,指定是否将每个文件作为单独的模块,默认为true,它不可以和declaration同时设定 */ /* Strict Type-Checking Options */ "strict": true /* strict的值为true或false,用于指定是否启动所有类型检查,如果设为true则会同时开启下面这几个严格类型检查,默认为false */, "noImplicitAny": true, /* noImplicitAny的值为true或false,如果我们没有为一些值设置明确的类型,编译器会默认认为这个值为any,如果noImplicitAny的值为true的话。则没有明确的类型会报错。默认值为false */ "strictNullChecks": true, /* strictNullChecks为true时,null和undefined值不能赋给非这两种类型的值,别的类型也不能赋给他们,除了any类型。还有个例外就是undefined可以赋值给void类型 */ "strictFunctionTypes": true, /* strictFunctionTypes的值为true或false,用于指定是否使用函数参数双向协变检查 */ "strictBindCallApply": true, /* 设为true后会对bind、call和apply绑定的方法的参数的检测是严格检测的 */ "strictPropertyInitialization": true, /* 设为true后会检查类的非undefined属性是否已经在构造函数里初始化,如果要开启这项,需要同时开启strictNullChecks,默认为false */ "noImplicitThis": true, /* 当this表达式的值为any类型的时候,生成一个错误 */ "alwaysStrict": true, /* alwaysStrict的值为true或false,指定始终以严格模式检查每个模块,并且在编译之后的js文件中加入"use strict"字符串,用来告诉浏览器该js为严格模式 */ /* Additional Checks */ "noUnusedLocals": true, /* 用于检查是否有定义了但是没有使用的变量,对于这一点的检测,使用eslint可以在你书写代码的时候做提示,你可以配合使用。它的默认值为false */ "noUnusedParameters": true, /* 用于检查是否有在函数体中没有使用的参数,这个也可以配合eslint来做检查,默认为false */ "noImplicitReturns": true, /* 用于检查函数是否有返回值,设为true后,如果函数没有返回值则会提示,默认为false */ "noFallthroughCasesInSwitch": true, /* 用于检查switch中是否有case没有使用break跳出switch,默认为false */ /* Module Resolution Options */ "moduleResolution": "node", /* 用于选择模块解析策略,有'node'和'classic'两种类型' */ "baseUrl": "./", /* baseUrl用于设置解析非相对模块名称的基本目录,相对模块不会受baseUrl的影响 */ "paths": {}, /* 用于设置模块名称到基于baseUrl的路径映射 */ "rootDirs": [], /* rootDirs可以指定一个路径列表,在构建时编译器会将这个路径列表中的路径的内容都放到一个文件夹中 */ "typeRoots": [], /* typeRoots用来指定声明文件或文件夹的路径列表,如果指定了此项,则只有在这里列出的声明文件才会被加载 */ "types": [], /* types用来指定需要包含的模块,只有在这里列出的模块的声明文件才会被加载进来 */ "allowSyntheticDefaultImports": true, /* 用来指定允许从没有默认导出的模块中默认导入 */ "esModuleInterop": true /* 通过为导入内容创建命名空间,实现CommonJS和ES模块之间的互操作性 */, "preserveSymlinks": true, /* 不把符号链接解析为其真实路径,具体可以了解下webpack和nodejs的symlink相关知识 */ /* Source Map Options */ "sourceRoot": "", /* sourceRoot用于指定调试器应该找到TypeScript文件而不是源文件位置,这个值会被写进.map文件里 */ "mapRoot": "", /* mapRoot用于指定调试器找到映射文件而非生成文件的位置,指定map文件的根路径,该选项会影响.map文件中的sources属性 */ "inlineSourceMap": true, /* 指定是否将map文件的内容和js文件编译在同一个js文件中,如果设为true,则map的内容会以//# sourceMappingURL=然后拼接base64字符串的形式插入在js文件底部 */ "inlineSources": true, /* 用于指定是否进一步将.ts文件的内容也包含到输入文件中 */ /* Experimental Options */ "experimentalDecorators": true /* 用于指定是否启用实验性的装饰器特性 */ "emitDecoratorMetadata": true, /* 用于指定是否为装饰器提供元数据支持,关于元数据,也是ES6的新标准,可以通过Reflect提供的静态方法获取元数据,如果需要使用Reflect的一些方法,需要引入ES2015.Reflect这个库 */ } "files": [], // files可以配置一个数组列表,里面包含指定文件的相对或绝对路径,编译器在编译的时候只会编译包含在files中列出的文件,如果不指定,则取决于有没有设置include选项,如果没有include选项,则默认会编译根目录以及所有子目录中的文件。这里列出的路径必须是指定文件,而不是某个文件夹,而且不能使用* ? **/ 等通配符 "include": [], // include也可以指定要编译的路径列表,但是和files的区别在于,这里的路径可以是文件夹,也可以是文件,可以使用相对和绝对路径,而且可以使用通配符,比如"./src"即表示要编译src文件夹下的所有文件以及子文件夹的文件 "exclude": [], // exclude表示要排除的、不编译的文件,它也可以指定一个列表,规则和include一样,可以是文件或文件夹,可以是相对路径或绝对路径,可以使用通配符 "extends": "", // extends可以通过指定一个其他的tsconfig.json文件路径,来继承这个配置文件里的配置,继承来的文件的配置会覆盖当前文件定义的配置。TS在3.2版本开始,支持继承一个来自Node.js包的tsconfig.json配置文件 "compileOnSave": true, // compileOnSave的值是true或false,如果设为true,在我们编辑了项目中的文件保存的时候,编辑器会根据tsconfig.json中的配置重新生成文件,不过这个要编辑器支持 "references": [], // 一个对象数组,指定要引用的项目}
第一个TypeScript实例
// 'xxx: number' 表示声明一个number类型的变量,他的值只能是numberconst num: number = 123// 声明一个函数的参数类型(数字以及字符串)和返回值(数组 数组项目是任意类型)function fn (arg1: number, arg2: string): Array { // todo return [1, 1, 2]}fn(num, '12123123')// 声明一个接口interface IPerson { name: string // IPerson需要包含一个name属性,类型是string age: number // IPerson需要包含一个age属性,类型是number family: string[] // IPerson需要包含一个family属性,类型是数组,数组里面都是string类型的数据 sex?: '男' | '女' // IPerson可选一个sex属性,值为'男'或者'女'或者undefined}// 使用IPerson接口定义一个对象,如果对象不符合IPerson的定义,编译器会飘红报错const person: IPerson = { name: '小刘', age: 12, family: ['爸爸', '妈妈'],}// type类似interface,以下写法等同用interface声明IPersontype IPerson2 = { name: string age: number family: string[] sex?: '男' | '女'}// 因此可以直接定义过来const person2: IPerson2 = person
Type Inference类型推论
-
如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
Type notes类型注解
-
let flag: boolean = false;
变量后面跟的冒号,后面的类型就是,这个变量的类型注解。类型的注解是可选的,不加就变成了JS,因为TS设计目标就是:兼容JS,减少js迁移TS的成本。
1.Array
数组有两种类型定义方式,一种是使用泛型:
const list: Array = [1, 2, 3]
另一种使用更加广泛那就是在元素类型后面接上 []:
const list: number[] = [1, 2, 3]
2.
元组(Tuple)
元组类型与数组类型非常相似,表示一个已知元素数量和类型的数组,各元素的类型不必相同。
比如,你可以定义一对值分别为string和number类型的元组。
let list: [string, number];
list = ['hello', 10, false] // Error
list = ['hello'] // Error
我们看到,这就是元组与数组的不同之处,元组的类型如果多出或者少于规定的类型是会报错的,必须严格跟事先声明的类型一致才不会报错。元组中包含的元素,必须与声明的类型一致,而且不能多、不能少,甚至顺序不能不符。可以理解为更加严格的数组
3.
枚举
它用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。枚举成员会被赋值为从 0
开始递增的数字,同时也会对枚举值到枚举名进行反向映射:
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 0); // trueconsole.log(Days["Mon"] === 1); // trueconsole.log(Days["Tue"] === 2); // trueconsole.log(Days["Sat"] === 6); // trueconsole.log(Days[0] === "Sun"); // trueconsole.log(Days[1] === "Mon"); // trueconsole.log(Days[2] === "Tue"); // trueconsole.log(Days[6] === "Sat"); // true
详细:https://ts.xcatliu.com/advanced/enum
4.
联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种。 联合类型使用 | 分隔每个类型。
let str: string | number;str = 1123;
str = '123';
Interface接口
-
Interface 是一种描述对象或函数的东西。
你可以把它理解为形状,一个对象需要有什么样的属性,函数需要什么参数或返回什么样的值,数组应该是什么样子的,一个类和继承类需要符合什么样的描述等等。
下文分七个部分,一起看一下对象接口、函数接口、可索引类型接口、类接口是如何定义的,以及接口的继承、定义混合类型的接口和继承类的接口是如何使用的。
1.
接口的简单定义和使用
1,接口一般首字母大写
2,定义的变量比接口 少一些属性 多一些属性 都是不允许的
interface User { name: string; age: number;}let people : User = { name: 'liu', age: 25};
2.
对象接口
interface User { name: string // 设置需要存在的普通属性 bool?: boolean // 设置可选属性 readonly birthday: string // 设置只读属性 readonly arr: ReadonlyArray// 此外还有 ReadonlyMap/ReadonlySet}let p1: User = { name: 'oliver', bool: true, // ✔️️ 可以设置可选属性 并非必要的 可写可不写 birthday: '1999-9-9', // ✔️ 设置只读属性 arr: [1, 2, 3] // ✔️ 设置只读数组}let p: User = { age: 'oliver', // ❌ 多出来的属性 name: 123 // ❌ 类型错误}p1.birthday = 123 // ❌ 只读属性不可修改p1.arr.pop() // ❌ 只读属性不可修改
3.
函数 Interface
Interface 还可以用来规范函数的形状。Interface 里面需要列出参数列表返回值类型的函数定义。写法如下:interface User { name: string; age: number; run: (type: string) => void}
interface Fun { // ✔️ 定于这个函数接收两个必选参数都是 number 类型,以及一个可选的字符串参数 desc,这个函数不返回任何值 (x: number, y: number, desc?: string): void}const count: Fun = function (x, y, desc = '') { // const count: Fun = function (x: number, y: number, desc: string): void { } // ts类型系统默认推论可以不必书写上述类型定义 console.log(desc, x + y)}count(32, 22)
4.
可索引类型
比如我们定义了一个接口但是该接口除了固定属性外可能还会有其他属性1个,或者多个的时候我们可以利用可索引类型实现interface Person { firstName: string; lastName: string; [index: string]: string}function greeter(person: Person) { return "Hello, " + person.firstName;}let user = { firstName: "Jane2", lastName: "User", aa: '1112', bb: 'cc' };document.body.innerHTML = greeter(user);
5.
Interface 的继承
跟 class 一样,使用 extens 继承一个接口,实现一个新接口,这个新的接口可以设定一个新的方法检查,并且保留以前的检查。interface PersonInfoInterface { // 1️⃣ 这里是第一个接口 name: string age: number log?(): void}interface Student extends PersonInfoInterface { // 2️⃣ 这里继承了一个接口 doHomework(): boolean // ✔️ 新增一个方法检查}interface Teacher extends PersonInfoInterface { // 3️⃣ 这里又继承了一个接口 dispatchHomework:() => void // ✔️ 新增了一个方法检查}// interface Emmm extends Student, Teacher // 也可以继承多个接口let Alice: Teacher = { name: 'Alice', age: 34, dispatchHomework() { // ✔️ 必须满足继承的接口规范 console.log('dispatched') }}let oliver: Student = { name: 'oliver', age: 12, log() { console.log(this.name, this.age) }, doHomework() { // ✔️ 必须满足继承的接口规范 return true }}
Class类
-
传统方法中,JavaScript 通过构造函数实现类的概念,通过原型链实现继承。而在 ES6 中,我们终于迎来了 class。
TypeScript 除了实现了所有 ES6 中的类的功能以外,还添加了一些新的用法。
1.
类的概念:
类(Class):定义了一件事物的抽象特点,包含它的属性和方法
对象(Object):类的实例,通过 new 生成
面向对象(OOP)的三大特性:封装、继承、多态
封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat
存取器(getter & setter):用以改变属性的读取和赋值行为
修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法
抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口
class my_class = { static num = 42; // 静态属性 name2 = 'name2' // es7中定义属性 constructor(name) { this.name = name; // es6中定义属性 } // getter方法 get render_table () { return '模版' } // setter方法 set save_table (value) { this.name = value } // 静态方法 static fn(a) { return 'aaa'; } sayHi() { return `My name is ${this.name}`; }}
3.
TypeScript 中类的用法
public private 和 protected
TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。
- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
class Car { readonly age = 0 private readonly color = 0 protected name: string = '车' protected readonly type = '轿车' protected stop() { console.log('熄火...') } private brake() { console.log('刹车...') } public run() { console.log('启动...') }}class GTR extends Car { init() { this.run() //可以访问 this.brake() // 不可以访问 console.log(this.age) // 可以访问 this.age = '11' // 不能修改 console.log(this.color) // 不可以访问 console.log(this.type) // 可以访问 this.type = 'asda' // 不可以修改 }}const car1 = new Car()console.log(this.name) // 不可以访问car1.run() // 可以访问car1.stop() // 不可以访问console.log(car1.age) // 可以访问car1.age = '123123' // 不可以修改console.log(car1.color) // 不可以访问
4.
抽象类
abstract 用于定义抽象类和其中的抽象方法。 什么是抽象类?首先,抽象类是不允许被实例化的:
抽象类中的抽象方法必须被子类实现:
abstract class Car { protected name: string = '车' protected stop() { console.log('熄火...') } public abstract brake(): void; public run() { console.log('启动...') }}class GTR extends Car { init() { this.run() //可以访问 } // 必须有brake方法 brake () { console.log('刹车...') }}const car1 = new Car() // 不允许实例化
Function函数
-
在TypeScript中定义函以前定义函数基本没什么区别,就是多了函数参数类型验证,函数返回值验证
1.
定义函数类型
const add = (a: number, b: number) => a + b// 或者const add = (a: number, b: number): string => { return ( a + b ) + ''}
2.
函数参数解释
const add = ( a: number, // 必须传递的参数 b: number = 100, // 必须传递的参数, 默认100 c?: number, // 可选择参数 ...reset: number[] // 剩余参数 必须放到最后 ): string => { return ( a + b ) + ''}
3.
重载
重载可以理解为,一个函数,有多种用法,通过传递参数的个数,传递参数的类型实现不同的功能,
比如jQuery里面的css方法
css('width') 获取width的值
css('width', 100) 设置width为100
css({width: 200, height: 100}) 设置多个样式属性
// 重载interface Direction { top: number right: number bottom: number left: number}function assigned(all: number): Directionfunction assigned(topAndBottom: number, leftAndRight: number): Directionfunction assigned(top: number, right: number, bottom: number, left: number): Direction// 代码实现函数不可被调用function assigned (a: number, b?: number, c?: number, d?: any) { if (b === undefined && c === undefined && d === undefined) { b = c = d = a } else if (c === undefined && d === undefined) { c = a d = b } return { top: a, right: b, bottom: c, left: d }}assigned(1) // okassigned(1, 1) // okassigned(1, 1, 1) // 报错assigned(1, 1, 1, 1) // ok
Generics泛型
-
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
1.
泛型变量
比如又一个函数我们需要的是接收什么类型返回什么类型,这样的情况下我们定义类型就不好定义了因为不确定,这个时候就可以使用泛型
function getNum (num: number): number { return num}getNum(1) // oketNum('1') // 错误// 使用泛型 T 在这里是随便写的一个字母function getNum <T>(num: T): T { return num}getNum(1) // oketNum('1') // ok// 如果多个类型的话可以function getNum <T, A>(num: [T, A ] ): [A, T] { return [num[1], num[0]]}getNum(1, '1') // oketNum('1', 1) // ok
2.
泛型接口
interface Foo { (arg: T): T}const foo: Foo = (arg: T): T => arg// 将泛型参数当作接口的一个参数,明确泛型类型interface Foo { (arg: T): T}// arg将会被推导为number类型const foo: Foo<number> = (arg) => arg
3.
泛型类
类分为静态部分和实例部分,泛型类指的是实例部分的类型,不能用于静态部分class Obj<T, U> { static name:T // error,静态成员不能泛型类型 constructor(public x: T, public y: U) {} getY(): U { return this.y } getX(): T { return this.x }}const obj = new Obj('name', 100)
4.
泛型约束
interface NameConstraint { name: string}// 约束了泛型参数T,必须包含name属性,而不是任意类型function witcher<T extends NameConstraint>(people: T): T { return people}// okwitcher({ name: 'geralt' })// error, 必须有name属性witcher('geralt')
Type Asserts
类型断言
-
类型断言其实就是告诉编辑器我自己知道结果是什么类型,不需要进行类型检查,避免不必要的错误,下面代码的执行其实就是我们在订阅函数的时候并没有返回对象中是否有a这个属性,正常第一种会报错,而使用了断言就不会报错了
interface Postion { a: '123'}function getNum (x:string, y:string):object { return {}}const num = (getNum('11', '22') as Postion).a; //正确const num2 = (getNum('11', '22')).a // 正确const num3 = getNum('11', '22').a // 报错
双重断言
虽然类型断言是有强制性的,但并不是万能的,因为一些情况下也会失效:
interface Postion { x: number; y: number;}const client = '文字' as Postion; // Errorconst client2 = '文字' as any as Postion; // Ok
Declare File编写声明文件 - 虽然 TypeScript 已经逐渐进入主流,但是市面上大部分库还是以 JavaScript 编写的,但是这些库没有像 TS 一样定义类型,因此需要一个声明文件来帮助库的使用者来获取库的类型提示。 简单点理解的话就是有些文件不是ts写的,我门需要用的时候,ts中没有定义,会报错,所以我门通过声明文件的形式来给对应的文件写类型提示 1. 声明文件语法declare var 声明全局变量
declare function 声明全局方法
declare class 声明全局类
declare enum 声明全局枚举类型
declare namespace 声明(含有子属性的)全局对象
interface 和 type 声明全局类型
export 导出变量
export namespace 导出(含有子属性的)对象
export default ES6 默认导出
export = commonjs 导出模块
export as namespace UMD 库声明全局变量
declare global 扩展全局变量
declare module 扩展模块
写法就是新建一个或多个 xxx.d.ts文件,里面做声明即可,ts会自动解析项目里面的所有xxx.d.ts文件 比如:declare const jQuery: (selector: string) => any;declare function jQuery(selector: string): any;declare class Person { name: string; constructor(name: string); say(): string;}declare enum Directions { Up, Down, Left, Right}declare namespace jQuery { function ajax(url: string, settings?: any): void;}interface AjaxSettings { method?: 'GET' | 'POST' data?: any;}declare namespace jQuery { function ajax(url: string, settings?: AjaxSettings): void;}
2.
声明合并
假如 jQuery 既是一个函数,可以直接被调用 jQuery('#foo'),又是一个对象,拥有子属性 jQuery.ajax()(事实确实如此),那么我们可以组合多个声明语句,它们会不冲突的合并起来:
// src/jQuery.d.tsdeclare function jQuery(selector: string): any;declare namespace jQuery { function ajax(url: string, settings?: any): void;}// src/index.tsjQuery('#foo');jQuery.ajax('/api/user_info');
3.
使用第三d.ts
Github 上有一个库 DefinitelyTyped 它定义了市面上主流的JavaScript 库的 d.ts ,而且我们可以很方便地用 npm 引入这些 d.ts。
比如我们要安装 JQuery 的 d.ts:
npm install @types/jquery -save
在日常开发中我们建议直接使用 DefinitelyTyped 定义的 d.ts,但是依然有些情况下我们需要给自己的库编写 d.ts,或者没有第三方的 d.ts 提供,这个时候就需要什么自己编写 d.ts 文件了.
Ok:差不多了,还有一些高级用法太多了,写不下去了,大家可以自行百度查阅资料去学习,加油我们一起跟随时代的脚步进步 春风十里都不如你的一个“在看”