⼀、TypeScript
简介
1 什么是TypeScript
?
TypeScript
本质上是向JavaScript
语⾔添加了「可选的静态类型」和「基于类的⾯向对象」编程,它相当于JavaScript
的超集
官⽅⽂档:
TypeScript
的官⽅⽂档⾮常⾮常适合前端开发者进阶学习使⽤,这个⾮常有助于我们突破我们的技术壁垒,建议⼤家⼀定要细细研读,不同阶段的开发者研读⽂档的感觉各有千秋,但都⼤有收获。
2 为什么选择TypeScript
?
TypeScript
增加了代码的可读性和可维护性
- 类型系统实际上是最好的⽂档,⼤部分的函数看看类型的定义就可以知道如何使⽤了
- 可以在编译阶段就发现⼤部分错误,这总⽐在运⾏时候出错好
- 增强了编辑器和IDE的功能,包括代码补全、接⼝提示、跳转到定义、代码重构等
TypeScript
非常包容
TypeScript
是JavaScript
的超集,.js
⽂件可以直接重命名为.ts
即可- 即使不显式的定义类型,也能够⾃动做出类型推论
TypeScript
的类型系统是图灵完备的,可以定义从简单到复杂的⼏乎⼀切类型- 即使
TypeScript
编译报错,也可以⽣成JavaScript
⽂件- 兼容第三⽅库,即使第三⽅库不是⽤
TypeScript
写的,也可以编写单独的类型⽂件供TypeScript
读取
TypeScript
拥有活跃的社区
- ⼤部分第三⽅库都有提供给
TypeScript
的类型定义⽂件Angular
、Vue
、VSCode
、AntDesign
等等⽿熟能详的项⽬都是使⽤TypeScript
编写的TypeScript
拥抱了ES6规范,⽀持ESNext草案中处于第三阶状态(Stage3)的特性
TypeScript
的弊端
- 有⼀定的学习成本,需要理解接⼝(
Interfaces
)、泛型(Generics
)、类(Classes
)、枚举类型(Enums
)等前端⼯程师可能不是很熟悉的概念- 短期可能会增加⼀些开发成本,毕竟要多写⼀些类型的定义,不过对于⼀个需要⻓期维护的项⽬,
TypeScript
能够减少其维护成本- 集成到构建流程需要⼀些⼯作量
- 可能和⼀些库结合的不是很完美
3 TypeScript
语法特性
TypeScript
是⼀种给JavaScript
添加特性的语⾔扩展。增加的功能包括:
- 类型批注(注解)和编译时类型检查
type annotation
- 类型推断
type inferrence
- 接⼝
interface+implements
- 枚举
enum
Mixins
- 泛型编程
<>
- 名字空间
namespace
- 元组
Tupe
Async
/Await
以下功能是从ECMA2015反向移植⽽来:
- 类
class
extends
继承类or抽象类implements
继承接⼝constructor
构造函数super
调⽤⽗类属性public
公共属性⽅法private
私有属性⽅法protected
保护属性⽅法readyonly
只读属性⽅法static
静态属性⽅法get getter
存取器set setter
存取器new
实例化对象abstract
抽象类- 类
class
的本质构造函数- 模块
module
lambda
函数箭头- 可选参数以及默认参数
4 TypeScript
基础数据类型
数据类型 关键字 描述 任意类型 any 声明为any的变量可以赋予任意类型的值。 数字类型 number 双精度64位浮点值。它可以⽤来表示整数和分数。 字符串类型 string 使⽤单引号「’’」或双引号「""」来表示字符串类型反引号;「``」来定义多⾏⽂本和内嵌表达式。 布尔类型 boolean 表示逻辑值:true和false 数组类型 ⽆ 声明变量为数组 元组 ⽆ 元组类型⽤来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同 枚举 enum 枚举类型⽤于定义数值集合 void void ⽤于标识⽅法返回值的类型,表示该⽅法没有返回值 null null 表示对象值缺失。 undefined undefined ⽤于初始化变量为⼀个未定义的值 never never never是其它类型(包括null和undefined)的⼦类型,代表从不会出现的值。 注意:
TypeScript
和JavaScript
没有整数类型
5 TypeScript
安装使用
1.全局安装
TypeScript
,使⽤tsc命令编译成JavaScript
代码npm install typescript -g yarn global add typescript mkdir `TypeScript`Demo // demo.ts funnction sayHi(): void{ let web: string = "hello world"; console.log(web); } sayHi(); tsc demo.ts
2.使⽤ts-node插件直接编译运⾏ts⽂件
npm install -g ts-node ts-node Demo.ts
⼆、TypeScript
类型的概念和使用
1 基础静态类型和对象类型
在
TypeScript
静态类型分为两种,⼀种是基础静态类型,⼀种是对象类型:
基础静态类型
基础静态类型⾮常简单,只要在声明变量的后边加⼀个:
号,然后加上对应的类型。⽐如下⾯的代码,就是声明了⼀个数字类型的变量,叫做count。const const: number = 88; const myNam: string = '蜡笔小新';
类似这样常⽤的基础类型还有:null, undifined,symbol,boolean, void
对象类型
经典对象类型,也是最简单的对象类型,如下:const laxx: { name: string, age: number } = { name: '蜡笔小新', age: 18 }
对象类型也可以是数组,如下:
const users: String[] = ["蜡笔小新", “犬夜叉”,“樱桃小丸子”]
对象类型也可以是类,如下:
class Person{ } // lbxx 必须是⼀个必须是⼀个Person实例化的对象实例化的对象 const lbxx: Person =new Person();
对象类型可以是函数类型,并确定返回值,如下:
const getName:() => string = () => { return "蜡笔小新" };
总结:对象类型形式
- 对象类型
- 数组类型
- 类类型
- 函数类型
2 类型注解和类型推断
type annotation
类型注解
前⾯我们学到的基础静态类型和对象类型的这种约束规则就叫做「类型注解」,如下:// 显示的告诉代码,我们的count变量就是⼀个数字类型,这就叫做类型注解 let count: number: count = 123;
type inference
类型推断
通过初始化设置值后,系统会⾃动推断属性的类型,并且不允许随意变动,这就是「类型推断」// `TypeScript`⾃动把变量注释为了number(数字)类型 let countInference = 123
⼯作使用问题(潜规则)
- 如果TS能够⾃动分析变量类型,我们就什么也不需要做了
- 如果TS⽆法分析变量类型的话,我们就需要使⽤类型注解
先来看⼀个不⽤写类型注解的例⼦:
const one = 1; const two = 2; const three = one + two;
再来看⼀个⽤写类型注解的例⼦:
function getTotal(one, two){ return one + two; } const total = getTotal(1, 2);
这种形式,就需要⽤到类型注释了,因为这⾥的one和two会显示为any类型。这时候如果你传字符串,你的业务逻辑就是错误的,所以你必须加⼀个类型注解,把上⾯的代码写成下⾯的样⼦。
function getTotal(one: number, two: number){ return one + two; } const total = getTotal(1, 2);
在写
TypeScript
代码的⼀个重要宗旨就是每个变量,每个对象的属性类型都应该是固定的,如果你推断就让它推断,推断不出来的时候你要进⾏注释。
3 函数参数和返回类型注解
简单类型注解
function getTotal(one: number, two: number){ return one + two; } const total = getTotal(1, 2);
我们并没有定义
getTotal
的返回值类型,虽然TypeScript
可以⾃⼰推断出返值是number类型,但是如果这时候我们的代码写错了,⽐如:function getTotal(one: number, two: number){ return one + two + ''; } const total = getTotal(1, 2);
这时候
total
的值就不是number
类型了,但是不会报错,我们给返回值设置静态属性,如下:const total: number = getTotal(1, 2);
这样写虽然可以让编辑器报错,但是这还不是很⾼明的算法,因为你没有找到错误的根本,这时错误的根本是
getTotal()
函数的错误,所以合适的做法是给函数的返回值加上类型注解,代码如下:function getTotal(one: number, two: number): number{ return one + two; } const total = getTotal(1, 2);
函数无返回值时定义方法
没有返回值的函数,我们就可以给他⼀个类型注解void
,代表没有任何返回值function sayHello(): void{ console.log("hello world"); }
never
返回值类型
如果⼀个函数是永远也执⾏不完的,就可以定义返回值为never
,⽐如执⾏执⾏的时候,抛出异常,这时候就⽆法执⾏完了,如下:function errorFuntion(): never { throw new Error(); console.log("hello world"); }
还有⼀种就是死循环,如下:
function forNever(): never { while(true){ } console.log("hello world"); }
函数参数为对象(解构)时使⽤类型注解
function add({ one, two}: { one: number, two: number}): number{ return one + two; } const three = add({ one: 1, two: 2);
4 数组类型的定义
单⼀数据类型数组的定义
const numberArr = [1, 2, 3];
TypeScript
会通过类型推断⾃⼰推断类型注解,当然也可以显式地声明数组类型注解const numberArr: number[] = [1, 2, 3]; const stringArr: string[] = ["a", "b", "c"]; const undefinedArr: undefined[] = [undefined, undefined];
多种数据类型数组类型注解
const arr: (number | string)[] = [ 1, 'string', 3]
数组中对象类型的定义
const users: { name: string, age: number }[] = [ { name: "蜡笔小新", age: 18 }, { name: "犬夜叉", age: 28 } ];
这种形式阅读麻烦,并且不便于复⽤,所有
TypeScript
为我们准备了⼀个概念,叫做类型别名「type alias」:type User = { name: string, age: number }; const users: User[] = [ { name: "蜡笔小新", age: 18 }, { name: "犬夜叉", age: 28 } ];
当然我们也可以使⽤类来作为类型注解约束:
class User{ name: string; age: number; }; const users: User[] = [ { name: "蜡笔小新", age: 18 }, { name: "犬夜叉", age: 28 } ];
5 interface
接口的使用
我们可以把这重复使⽤的类型注解,定义成统⼀的接⼝,⽐如:
interface User{ name: string; age: number; };
接口和类型别名的区别
类型别名type
可以直接给类型,也可以给对象类型,如下:type User = string, const lbxx: User = '蜡笔小新'; };
接⼝
interface
必须代表对象,如下:interface User{ name: string; age: number; }; const users: User = { name: '蜡笔小新', age: 18 };
接口非必选值得定义
在:
号前加⼀个?
代表当前接⼝属性是⾮必选项interface User{ name: string; age: number; like?: string; };
允许加入任意值
interface User{ name: string; age: number; like?: string; [propname: string]: any; };
这个的意思是,属性的名字是字符串类型,属性的值可以是任何类型
接口里的方法
接⼝⾥不仅可以存属性,还可以存⽅法,⽐如:interface User{ name: string; age: number; like?: string; [propname: string]: any; // 需要注意的使:加了方法后作为类型注解使用时,对象必须要有该方法 say(): string; };
接口和类的约束
类可以和接⼝很好的结合,⽐如:class Teacher implements User{ name = "蜡笔小新"; age = 18; say(){ return "你好,我是蜡笔小新" }; };
接口间的继承
接口也可以⽤于继承的,⽐如你新写⼀个Admin接⼝,继承于User接⼝。interface Admin extends User { admin(): string; }
const qyx: Admin = { name: "黑猫警长", age: 18, say() { return "你好,我是黑猫警长"; }, admin() { return "我是管理员"; }, }
6 联合类型和类型保护
联合类型展示
所谓联合类型,可以认为⼀个变量可能有两种或两种以上的类型,关键符号是
|
竖线class MathTeacher { public compute(): void { console.log('数学老师会算数') } } class EnglishTeacher { public say(): void { console.log('英语老师说Hello') } } function teacherTeach( teacher: MathTeacher | EnglishTeacher): void { }; const lucy = new MathTeacher( 'Lucy', '乡村小学') // ҅这个时候,teacherTeach这个方法不能判定lucy是数学老师或者英语老师 teacherTeach(lucy)
类型保护
类型保护-类型断言
直接调⽤联合类型的⽅法提示异常,因为teacherTeach⽅法不能准确的判断联合类型的具体实例是什么class MathTeacher { public compute(): void { console.log('数学老师会算数') } } class EnglishTeacher { public say(): void { console.log('英语老师说Hello') } } function teacherTeach( teacher: MathTeacher | EnglishTeacher): void { // teacher.say() // teacher.compute() }; const lucy = new MathTeacher( 'Lucy', '乡村小学') teacherTeach(lucy)
这时候就需要再引出⼀个概念叫做类型保护,类型断⾔就是通过断⾔的⽅式确定传递过来的准确值
class MathTeacher { public compute(): void { console.log('数学老师会算数') } } class EnglishTeacher { public say(): void { console.log('英语老师说Hello') } } function teacherTeach( teacher: MathTeacher | EnglishTeacher): void { (teacher as EnglishTeacher).say(); (teacher as MathTeacher).compute() }; const lucy = new MathTeacher('Lucy', '乡村小学') teacherTeach(lucy)
类型保护-in语法
class MathTeacher { public compute(): void { console.log('数学老师会算数') } } class EnglishTeacher { public say(): void { console.log('英语老师说Hello') } } function teacherTeach( teacher: MathTeacher | EnglishTeacher): void { if( "compute" in teacher) { teacher.compute() } else { teacher.say() } }; const lucy = new MathTeacher('Lucy', '乡村小学') teacherTeach(lucy)
类型保护-instanceof语法
class MathTeacher { public compute(): void { console.log('数学老师会算数') } } class EnglishTeacher { public say(): void { console.log('英语老师说Hello') } } function teacherTeach( teacher: MathTeacher | EnglishTeacher): void { if( teacher instanceof Mathteacher) { teacher.compute() } else { teacher.say() } }; const lucy = new MathTeacher('Lucy', '乡村小学') teacherTeach(lucy)
7 Enmu枚举类型
使⽤枚举我们可以定义⼀些带名字的常量,使⽤枚举可以清晰地表达意图或创建⼀组有区别的⽤例,
TypeScript
⽀持数字的和基于字符串的枚举。// 数字枚举 enum Direction{ Up = 1, // 设置初始增长的值,后面递增+1 Down, Left, Right } // 字符串枚举 enum Direction{ Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", }
三、TypeScript
中类的概念和使用
1 类的基本使用
类的基本使⽤
class Person { content = "Hi, 老铁"; sayHello() { return this.content; } } const lbxx = new Person(); console.log( lbxx.sayHello() );
类的继承
class Person { content = "Hi, 老铁"; sayHello() { return this.content; } } class Teacher extends Person{ teach() { return "我是teacher, 也是Person" } } const lbxx = new Teacher(); console.log( lbxx.sayHello() ); console.log( lbxx.teach() );
类的重写
class Person { content = "Hi, 老铁"; sayHello() { return this.content; }; teach() { return "我是Person, what can I do for you?" } } class Teacher extends Person{ teach() { return "我是teacher, 也是Person" } } const lbxx = new Teacher(); console.log( lbxx.teach() );
super
关键字的使⽤class Person { content = "Hi, 老铁"; teach() { return "我是Person, what can I do for you?" } } class Teacher extends Person{ teach() { return super.content + super.teach() +"我是teacher, 也是Person" } } const lbxx = new Teacher(); console.log( lbxx.teach() );
2 类的访问类型
public
访问属性
public
从英⽂字⾯的解释就是公共的或者说是公众的,在程序⾥的意思就是允许在类的内部和外部被调⽤,public
也是类中默认的访问属性class Person { public name: string; }
private
访问属性
private
访问属性的意思是,只允许再类的内部被调⽤,外部不允许调⽤class Person { private name: string; public sayHello() { console.log(this.name + "say Hi"); // 此处不报错 }; } const person = new Persion(); person.name = "lbxx"; // 此处报错 person.sayHello(); console.log(person.name); // 此处报错
protected
访问属性
protected
允许在类内及继承的⼦类中使⽤class Person { protected name: string; public sayHello() { console.log(this.name + "say Hi"); }; } class Teacher extends Person { public sayBye() { console.log(this.name + "say Bye"); }; }
readonly
只读属性class Person { public readonly _name: string; constructor(name: string) { this._name = name; }; } const person = new Persion("lbxx"); person._name = "ytxwz"; // 此处报错 console.log(person._name);
static
静态属性
static声明的属性和⽅法,不需要进⾏声明对象,就可以直接使⽤class Person { static sayHello() { return "Static function says Hi"; }; } console.log(Person.sayHello());
3 构造函数
构造函数的关键字是
constructor
class Person { public name: string; constructor(name: string) { this._name = name; }; } const person = new Person("lbxx"); console.log(person.name);
如果属性直接匹配使⽤,则可以进⾏简写
class Person { constructor( public name: string) { this._name = name; }; } const person = new Person("lbxx"); console.log(person.name);
类继承中的构造器写法
在⼦类中使⽤构造函数需要⽤super()
调用父类的构造函数,⼦类继承父类并有构造函数的原则,就是在⼦类⾥写构造函数时,必须⽤super()
调用父类的构造函数,如果需要传值,也必须进⾏传值操作class Person { constructor( public name: string) { this._name = name; }; } class Teacher extends Person{ constructor(public name: string, public age: number){ super(this.name) } } const teacher = new Teacher("lbxx", 20); console.log(teacher.name, teacher.age);
4 类的Getter和Setter
对私有属性
private
的外部访问,需要使⽤Getter
class User { constructor( public _age: number) { }; get age(){ return "年龄保密" } } const lbxx = new User(22); consoe.log(lbxx.age);
对私有属性
private
的外部加⼯,需要使⽤Setter
class User { constructor( public _age: number) { }; // 外部访问会主动调用 get age(){ return this._age + 18 } // 内部方位会主动调用 set age(){ this._age = age + 18; } } const lbxx = new User(22); consoe.log(lbxx.age); lbxx.age = 50; consoe.log(lbxx.age);
5 abstract抽象类使⽤
抽象类的关键词是
abstract
,⾥边的抽象⽅法也是abstract
开头的,抽象⽅法需要在被继承的
类中被覆盖重写,并且必须包含这个抽象⽅法,代表的是⼀种约束abstract class Teacher { constructor( public name: string, public school: string) { }; public abstract skill(): void } class MathTeacher extends Teacher{ skill(){ console.log('数学老师教数学') } public compute(): void{ console.log('数学老师会计算') } } class EnglishTeacher extends Teacher{ skill(){ console.log('English Teacher teaches English' ) } public say(): void{ console.log('英语来时问好说 hello') } } const lucy = new MathTeacher('lucy', '乡村小学') lucy.skill();
四、TypeScript
泛型的概念和使用
1 泛型基础使用
泛型的基础使用
泛型:[generic-通⽤、泛指的意思],那最简单的理解,泛型就是泛指的类型。
泛型的定义使⽤<>
(尖角号)进行定义的,尖括号内定义参数就是泛型名称,然后在正式调⽤的时候使⽤这个名词即可,我们⼀般使⽤作为泛型使⽤function join<T>(first: T, second: T){ return `${ first}${ second}`; } join <string> ("lbxx", "ytxwz")
如果要是
number
类型,就直接在调用方法的时候进⾏更改就可以了join <number> (1, 2);
泛型中数组的使用
如果传递过来的值要求是数字,如何⽤泛型进⾏定义那?两种⽅法,第⼀种是直接使⽤[[]],第⼆种是使⽤Array
<泛型>。形式不⼀样,其他的都⼀样。
第⼀种写法:function myFun<ANY>( params: ANY[]) { return params; } myFun <string> [ "123", "456"];
第⼆种写法:
function myFun<ANY>( params: Array[ANY]) { return params; } myFun <string> [ "123", "456"];
在⼯作中,我们经常使⽤
<T>
来作泛型的表示,当然这不是硬性的规定,只是⼤部分程序员的习惯性写法。
多个泛型的定义
⼀个函数可以定义多个泛型,⽐如第⼀个泛型⽤T
,第⼆个⽤P
代表function join<T, P>(first: T, second: P){ return `${ first}${ second}`; } join <string, number> ("lbxx", 20)
泛型的类型推断
泛型也是⽀持类型推断的,⽐如下⾯的代码就是类型推断的功劳。
function join<T, P>(first: T, second: P){ return `${ first}${ second}`; } join("lbxx", 20)
但不建议大量使用类型推断,这会让你的代码易读和健壮性都会下降
(2)泛型在类中的使⽤
初始类的泛型
基础⼀个类代码class SelectTeacher { constructor( private teachers: string[] | number[]){ } getOneTeacher( index: number): string | number{ return this.teachers[index]; } }
使⽤泛型重构代码
class SelectTeacher<T> { constructor( private teachers: T[]){ } getOneTeacher( index: number): T { return this.teachers[index]; } } const teachers = new SelectTeacher(['lbxx', 'ytxwz', 'qyc']); console.log(teachers.getOneTeacher(1));
const teachers = new SelectTeacher<string>(['lbxx', 'ytxwz', 'qyc']);
泛型中的继承
定义⼀个Teacher
接⼝interface Teacher{ name: string; age: number; }
使⽤
extends
关键字实现泛型继承interface Teacher{ name: string; age: number; } class SelectTeacher<T extends Teacher> { constructor( private teachers: T[]){ } getOneTeacher( index: number): T { return this.teachers[index]; } } const teachers = new SelectTeacher([{ name: 'lbxx', age: 18 },{ name: 'ytxwz', age: 30 }]); console.log(teachers.getOneTeacher(0));
泛型约束
泛型可以是任意类型,可以是对象、字符串、布尔、数字都是可以的,如果我们约束泛型为指定的类型,这就叫做泛型约束interface Teacher{ name: string; age: number; } class SelectTeacher<T extends Teacher> { constructor( private teachers: T[]){ } getOneTeacher( index: number): T { return this.teachers[index]; } } const teachers = new SelectTeacher()<string>['lbxx', 'ytxwz', 'qyc'] console.log(teachers.getOneTeacher(1));
五、配置⽂件tsconfig.json使用
1 配置⽂件基础使用
tsconfig.json
⽣效使⽤
- 通过
tsc --init
命令⽣成tsconfig.json
⽂件,tsconfig.json
⽂件也叫做TypeScript
编译配置⽂件- 让
tsconfig.json
⽂件⽣效,使⽤tsc demo.ts
进⾏编译,编译后会得到demo.js
⽂件,但是tsconfig.json
⽂件并⽣效- 打开
tsconfig.json
⽂件,找到complilerOptions
属性下的removeComments: true
选项,把注释去掉,这个配置项的意思是,编译时不显示注释,也就是编译出来的js⽂件不显示注释内容- 这时候再运⾏编译代码
tsc demo.ts
,编译后打开demo.js
⽂件,你会发现注释依然存在,说明tsconfig.json
⽂件没有起作⽤- 如果要想编译配置⽂件起作⽤,我们可以直接运⾏
tsc
命令,这时候tsconfig.json
才起作⽤,可以看到⽣成的js
⽂件已经不带注释了
多个ts⽂件选择性配置⽣效
默认⽂件体系下的多个
ts
⽂件都会同时被编译⽣效使⽤
include
配置⽤来指定要编译的⽂件的,⽐如现在我们只编译demo.ts
⽂件,⽽不编译demo2.ts
⽂件,就可以这样写。
注意:配置⽂件不⽀持单引号,所以⾥边都要使⽤双引号;使⽤files
的配置效果和include
⼏乎⼀样{ "include": ["demo.ts"], // "files": ["demo.ts"], "complierOptions": { // any something // ... } }
使⽤
exclude
配置⽤来说明除了指定的⽂件需要编译外其他⽂件不需要被编译,⽐如不编译demo2
只编译demo
{ "exclude": ["demo2.ts"], "complierOptions": { // any something // ... } }
2 complierOptions配置项详解
rootDir
和outDir
现在你的
js
⽂件直接编译到了根⽬录下,和ts
⽂件混在了⼀起。我们当然是不喜欢这种⽅法的,⼯作中我们希望打包的jjss都⽣成在特定的⼀个⽂件夹⾥,⽐如build
。这时候你就可以通过配置
outDir
来配置,当然你也可以通过rootDir
来指定ts
⽂件的位置,⽐如我们把所有的ts⽂件都放到src下。那配置⽂件就应该这样写。{ "outDir": "./build", "rootDir": "./src", }
编译ES6语法到ES5语法-
allowJs
- 现在你在
src
⽬录下⽤ES6
的语法写了⼀个demo2.js
⽂件,代码如下。export const name = "lbxx"
- 如果你不做任何配置,这时候使⽤
tsc
是没有效果的,我们需要到tsconfig.js
⽂件⾥修改配置"target": 'es5', // 这一项默认是开启的,必须保证开启才能转换成功 "allowJS": true, // 这个配置项的意思是联通
sourceMap
属性
- 如果把
sourceMap
的注释去掉,在打包的过程中就会给我们⽣成sourceMap
⽂件。sourceMap
简单说,Sourcemap
就是⼀个信息⽂件,⾥⾯储存着位置信息。也就是说,转换后的代码的每⼀个位置,所对应的转换前的位置。有了它,出错的时候,编译⼯具将直接显示原始代码,⽽不是转换后的代码,这⽆疑给开发者带来了很⼤⽅便
noUnusedLocals
和noUnusedParameters
⽐如现在我们修改demo.ts⽂件的代码,改为下面的样⼦。
const myName: string = null; export const name = "lbxx";
这时候你会发现
myname
这个变量没有任何地⽅使⽤,但是我们编译的话,它依然会被编译出来,这就是⼀种资源的浪费。这时候我们可以开启
noUnusedLocals:true
,开启后我们的程序会直接给我们提示不能这样编写代码,有没有使⽤的变量。
noUnusedParameters
是针对于没有使⽤的函数的,⽅法和noUnusedLocals:true
⼀样
更多编译选项详解,咱们还是到
TypeScript
官⽹查阅更多细节,TS的官⽅中⽂⽂档确实⾮常⾮常值得细细研读: https://www.tslang.cn/docs/handbook/compiler-options.html