【TypeScript】TypeScript基础与配置

⼀、TypeScript简介

1 什么是TypeScript

TypeScript本质上是向JavaScript语⾔添加了「可选的静态类型」和「基于类的⾯向对象」编程,它相当于JavaScript的超集
在这里插入图片描述

官⽅⽂档: TypeScript的官⽅⽂档⾮常⾮常适合前端开发者进阶学习使⽤,这个⾮常有助于我们突破我们的技术壁垒,建议⼤家⼀定要细细研读,不同阶段的开发者研读⽂档的感觉各有千秋,但都⼤有收获。

2 为什么选择TypeScript

TypeScript增加了代码的可读性和可维护性

  • 类型系统实际上是最好的⽂档,⼤部分的函数看看类型的定义就可以知道如何使⽤了
  • 可以在编译阶段就发现⼤部分错误,这总⽐在运⾏时候出错好
  • 增强了编辑器和IDE的功能,包括代码补全、接⼝提示、跳转到定义、代码重构等

TypeScript非常包容

  • TypeScriptJavaScript的超集,.js⽂件可以直接重命名为.ts即可
  • 即使不显式的定义类型,也能够⾃动做出类型推论
  • TypeScript的类型系统是图灵完备的,可以定义从简单到复杂的⼏乎⼀切类型
  • 即使TypeScript编译报错,也可以⽣成JavaScript⽂件
  • 兼容第三⽅库,即使第三⽅库不是⽤TypeScript写的,也可以编写单独的类型⽂件供TypeScript读取

TypeScript拥有活跃的社区

  • ⼤部分第三⽅库都有提供给TypeScript的类型定义⽂件
  • AngularVueVSCodeAntDesign等等⽿熟能详的项⽬都是使⽤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)的⼦类型,代表从不会出现的值。

注意:TypeScriptJavaScript 没有整数类型

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⽣效使⽤

  1. 通过tsc --init命令⽣成tsconfig.json⽂件,tsconfig.json⽂件也叫做TypeScript编译配置⽂件
  2. tsconfig.json⽂件⽣效,使⽤tsc demo.ts进⾏编译,编译后会得到demo.js⽂件,但是tsconfig.json⽂件并⽣效
  3. 打开tsconfig.json⽂件,找到complilerOptions属性下的removeComments: true选项,把注释去掉,这个配置项的意思是,编译时不显示注释,也就是编译出来的js⽂件不显示注释内容
  4. 这时候再运⾏编译代码tsc demo.ts,编译后打开demo.js⽂件,你会发现注释依然存在,说明tsconfig.json⽂件没有起作⽤
  5. 如果要想编译配置⽂件起作⽤,我们可以直接运⾏tsc命令,这时候tsconfig.json才起作⽤,可以看到⽣成的js⽂件已经不带注释了

多个ts⽂件选择性配置⽣效

  1. 默认⽂件体系下的多个ts⽂件都会同时被编译⽣效

  2. 使⽤include配置⽤来指定要编译的⽂件的,⽐如现在我们只编译demo.ts⽂件,⽽不编译demo2.ts⽂件,就可以这样写。
    注意:配置⽂件不⽀持单引号,所以⾥边都要使⽤双引号;使⽤files的配置效果和include⼏乎⼀样

    {
           
           
        "include": ["demo.ts"],
        // "files": ["demo.ts"],
        "complierOptions": {
           
           
            // any something
            // ...
        }
    }
    
  3. 使⽤exclude配置⽤来说明除了指定的⽂件需要编译外其他⽂件不需要被编译,⽐如不编译demo2只编译demo

    {
           
           
        "exclude": ["demo2.ts"],
        "complierOptions": {
           
           
            // any something
            // ...
        }
    }
    

2 complierOptions配置项详解

rootDiroutDir

  • 现在你的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就是⼀个信息⽂件,⾥⾯储存着位置信息。也就是说,转换后的代码的每⼀个位置,所对应的转换前的位置。有了它,出错的时候,编译⼯具将直接显示原始代码,⽽不是转换后的代码,这⽆疑给开发者带来了很⼤⽅便

noUnusedLocalsnoUnusedParameters

  • ⽐如现在我们修改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

猜你喜欢

转载自blog.csdn.net/qq_38987146/article/details/114860912