TypeScript手把手教程,简单易懂
简介
TypeScript (简称 ts)是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发
超集:也就是说 typescript有javascript没有的功能用来增强javascript
准备工作
-
安装(在node环境下)
npm i -g typescript or yarn global add typescript
-
检查是否安装成功
tsc -v 注意:tsc只有安装完typescript才有
-
体验
创建文件夹demo,在此文件下创建helloTs.ts,然后文件中,随便写点什么const s:string = "床前明月光,疑是地上霜"; console.log(s);
控制台执行 tsc helloTs.ts 命令,目录下生成了一个同名的 helloTs.js 文件,代码如下
var s = "床前明月光,疑是地上霜"; console.log(s);
通过tsc命令,发现我们的typescript代码被转换成了熟悉的js代码
我们接着执行node helloTs.js
即可看到输出结果
以上代码不理解没事,好好阅读练习下面详解就是发现新大陆
工作流
由于ts代码无法在浏览器中运行,所以编写的ts代码(Code.ts)由ts的编译器tsc进行编译代码(Code.ts)编译成功后会自动创建改ts所对应的js代码(Code.js)
JavaScript 和 TypeScript 的区别
- JavaScript:边解释边执行,错误只有在运行的时候才能发现
- TypeScript:先编译再执行,在写的时候就会发现错误了(ts不能直接执行,需要先编译成 js )
ts的好处
有利于规范我们的代码、代码编译阶段能更好的发现错误、强类型语言
入门必须
类型注解
就是给变量添加类型约束,可以显示标记出代码中的意外行为,从而降低了发生错误的可能性
格式:let 变量名: 类型 = 初始值
例:let name:string = ‘张三’
已知js原有类型:
- 原始类型:string、number、boolean、null、undefined、symbol
- 对象类型:object(包括,数组、对象、函数等对象)
ts新增类型:tuple(元组)、enum(枚举)、void、never、any、unknown、联合类型、字面量类型
用法
-
原有类型
// 字符串类型 let myName: string = '张三' // 数值类型 let age: number = 18 // 布尔类型 let isLoading: boolean = false // undefined let un: undefined = undefined // null let timer: null = null // symbol let uniKey: symbol = Symbol() //数组 let array1: number[] = [1,2,3,4,5] //or let array2: Array<number> = [1,2,3,4,5] //对象 let obj: {name:string, age:number} = {name: '张三', age: 18} //函数 let fun: (num1: number, num2: number) => number = function (num1: number, num2: number) { return num1 + num2; } console.log(fun(1, 2)); // 3 // 注意冒号后面是什么类型,值就必须是什么类型,否则编译会报相关错误 ↓ // Type 'string' is not assignable to type 'number'.
注意
默认情况下(非严格模式) null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给其他类型。
如果你在tsconfig.json指定了"strictNullChecks":true ,null 和 undefined 只能赋值给 void 和它们各自的类型。 -
新增类型
-
tuple(元组)
元组(Tuple)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。
元组用于精确描述一组值的类型,?
表示可选元素。它约定了的元素个数
它约定了特定索引对应的数据类型// 普通限制 let arr1: [number, string] // 可选限制 let arr2: [number, string?] // 任意数量限制 let arr3: [number, ...string[]] arr1 = [1, '张三'] arr2 = [1] arr2 = [1, '张三'] arr3 = [1, '张三', '李四', '王二', '麻子']
-
enum(枚举)
使用枚举我们可以定义一些有名字的数字常量。枚举通过enum关键字定义。//定义一个颜色枚举类 enum Color{ red, green, blue, } //使用 let color = Color.red; console.log(color) // 0 //注意: 枚举中的对应的值默认从0开始以此类推 //修改其值 enum Color2{ red = 'red', green = 10, blue = 'blue' }
-
void
通常用于函数返回值,定义一个函数没有返回任何东西,可以认为返回void
可以用到void 有以下几种情况:- 函数没写return
- 只写了 return, 没有具体的返回值
- return 的是 undefined
// 如果什么都不写,此时,add 函数的返回值类型为: void const add = () => {} // 如果return之后什么都不写,此时,add 函数的返回值类型为: void const add2 = () => { return } const add3 = (): void => { // 此处,返回的 undefined 是 JS 中的一个值 return undefined } // 这种写法是明确指定函数返回值类型为 void,与上面不指定返回值类型相同 const add4 = (): void => {}
-
never
通常应用于函数,当函数未执行完(报错、死循环)时改函数的返回值为never// 表示永远不会有返回结果 function throwError(message:string, errorCode:number): never { throw { message, errorCode } }
注意:不能将never作为变量的类型,这样无意义
-
any
表示任意类型,对声明该any类型的变量它的值可以是任意类型let n: any; //表示该变量 n 的值可以是任意类型 n = 123; n = '123'; n = true; // ...
-
unknown
表示未知类型的值,也可是任意类型let n: unknown; //表示该变量 n 的值可以是任意类型 n = 123; n = '123'; n = true; // ...
拓展》》》
any、unknown 区别?
any 类型的变量可以直接赋值给其他变量
unknown 类型的变量不能直接赋值给其他变量let a:any a= 123; a= 'object' let b: string b = a // ok let c: unknown; c = 123 c = '123' let d: number; d = c // Type 'unknown' is not assignable to type 'number'.
声明特殊类型
对象类型
// 普通限制
let person: {name: string, age: number}
// 可选限制
let person2: {name: string; age?: number}
// 索引签名
let person3: {
name: string
age?: number
[key: string]: any
}
// 以下赋值均可以
person = {name: '张三', age: 20}
person2 = {name: '张三'}
person2 = {name: '张三', age: 20}
person3 = {name: '张三', gender: '男'}
函数类型
let count: (a: number, b: number) => number
// 表示给count赋值必须要遵守上面限制的函数类型
count = function(x, y) {
return x + y
}
注意:
TypeScript 中的 => 在函数类型声明时表示函数类型,描述其参数类型和返回类型;
JavaScript 中的 => 是一种定义函数的语法,是具体的函数实现;
数组类型
let arr1: string[]
let arr2: Array<number>
// 以下赋值均可以
arr1 = ['a', 'b', 'c']
arr2 = [1, 2, 3]
注意: 上述代码里的Array<number>
属于泛型下面会讲到
类型断言
就是告诉编译器,我知道这个值是什么类型,也知道自己在干什么
格式: 1. <类型>变量名
2. 变量名 as 类型
例如:
// 返回一个数字或字符串的长度
function getString(val: string | number): number {
// 此时ts类型推导不知道val是string还是number,需要指定这个val此时的类型是string
if ((<string>val).length) {
// 使用第二种断言格式
return (val as string).length;
} else {
// 此时说明val的类型的number
return val.toString().length;
}
}
console.log(getString(123)); // 3
console.log(getString("1234")); // 4
类型别名
在我们定义类型的时候,有时候自己定义的类型名往往很长,这个时候就需要在定义个别名,方便书写。
格式:type 别名 = 类型
type s = string // 定义
const str1:s = 'abc' // 使用
const str2:string = 'abc'
作用:
- 给类型起别名
- 定义了新类型
使用场景:给复杂的类型起个别名,比如:多个联合类型
type NewType = string | number
let a: NewType = 1
let b: NewType = '1'
联合类型
需求:如何定义一个变量可以是 string 也可以是 number 类型? 这个时候,前面所学的已经不能满足我们的需求了,就需要用到一个新的类型 - 联合类型。
let a: number | string; // 变量a可以写两个类型
a = 123;
a = '123';
a = true; // 报错 Type 'boolean' is not assignable to type 'string | number'.
注意:冒号后面的类型可以有多个 用 | 竖线分割;例如:let b: number | string | null | …;
由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种。不要和 js 中的 || 搞混哦
字面量类型
在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型。对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型。
说白了就是某个变量的类型是一个或多个固定的值就是字面量类型
let str: 'hello world' = 'hello world'; // 表示该 str 值必须是 hello world
let num: 996 = 996; // 表示该 num 值必须是 996
let bool: true = true; // 表示该 bool 值必须是 true
//搭配联合类型使用
let age: 18 | 20 | 25 | 30; // age的值必须是 冒号后面类型其中一个
age = 18; //ok
age = 60;// 报错 Type '60' is not assignable to type '18 | 20 | 25 | 30'.
// 数字字面量类型也是一样的:
function compare(a: string, b: string): -1 | 0 | 1 {
return a === b ? 0 : a > b ? 1 : -1;
}
字面量推断
当你初始化变量为一个对象的时候,TypeScript 会假设这个对象的属性的值未来会被修改,举个例子,如果你写下这样的代码:
const obj = { counter: 0 };
if (someCondition) {
obj.counter = 1;
}
TypeScript 并不会认为 obj.counter 之前是 0, 现在被赋值为 1 是一个错误。换句话说,obj.counter 必须是 number 类型,但不要求一定是 0,因为类型可以决定读写行为。
这也同样应用于字符串:
//以declare声明的变量和模块后,其他地方不需要引入,就可以直接使用了;
//declare就是告诉TS编译器你担保这些变量和模块存在,并声明了相应类型,编译的时候不需要提示错误!
declare function handleRequest(url: string, method: "GET" | "POST"): void;
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
// Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
在上面这个例子里,req.method 被推断为 string ,而不是 “GET”,因为在创建 req 和 调用 handleRequest 函数之间,可能还有其他的代码,或许会将 req.method 赋值一个新字符串比如 “Guess” 。所以 TypeScript 就报错了。
有两种方式可以解决:
- 添加一个类型断言改变推断结果:
修改 1 表示“我有意让 req.method 的类型为字面量类型 “GET”,这会阻止未来可能赋值为 “Guess” 等字段”。// Change 1: const req = { url: "https://example.com", method: "GET" as "GET" }; // Change 2 handleRequest(req.url, req.method as "GET");
修改 2 表示“我知道 req.method 的值是 “GET””。 - 你也可以使用 as const 把整个对象转为一个类型字面量:
as const 效果跟 const 类似,但是对类型系统而言,它可以确保所有的属性都被赋予一个字面量类型,而不是一个更通用的类型比如 string 或者 number 。const req = { url: "https://example.com", method: "GET" } as const; handleRequest(req.url, req.method);
类(Class)
与js的类相似,可以理解为对象的模板,包含属性和方法
格式: class 类名 (类名首字母大写)
class Greeter {
// 属性
greeting: string;
// 构造函数
constructor(message: string) {
this.greeting = message;
}
// 方法
greet() {
return "Hello, " + this.greeting;
}
}
//根据类的构造函数创建对象
let greeter = new Greeter("world");
类的修饰符
-
访问修饰符
public
声明属性和方法(默认) 在哪个地方都可以访问属性、方法class Point { public x: number; public y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } public getPosition() { return `(${this.x}, ${this.y})`; } } const point = new Point(1, 2) console.log(point.x) // 1 console.log(point.y) // 2 console.log(point.getPosition()) // (1, 2)
private
声明属性和方法 将属性和方法私有化 外界不能访问class Parent { private age: number; constructor(age: number) { this.age = age; } } const p = new Parent(18); console.log(p); // { age: 18 } console.log(p.age); // 报错 Property 'age' is private and only accessible within class 'Parent'. console.log(Parent.age); // 报错 Property 'age' does not exist on type 'typeof Parent'. class Child extends Parent { constructor(age: number) { super(age); console.log(super.age); // Property 'age' is private and only accessible within class 'Parent' } }
protected
声明属性和方法 与private相似,区别是在继承中子可以访问父的protectedclass Parent { protected age: number; constructor(age: number) { this.age = age; } protected getAge() { return this.age; } } const p = new Parent(18); console.log(p.age); // 报错 Property 'age' is protected and only accessible within class 'Parent' and its subclasses. console.log(Parent.age); // 报错 Property 'age' does not exist on type 'typeof Parent'. class Child extends Parent { constructor(age: number) { super(age); console.log(super.getAge()); } } new Child(19)
-
只读修饰符
在类中可以使用readonly
关键字将属性设置为只读class UserInfo { readonly name: string; constructor(name: string) { this.name = name; } } const user = new UserInfo("TypeScript"); user.name = "haha"; // error Cannot assign to 'name' because it is a read-only property
-
静态修饰符
在类中可以使用static
关键字将属性或方法设置为静态类型class Parent { static age: number = 18; static getAge() { return Parent.age; } constructor() { // } } // 静态类型不用实例化对象直接用 类名. 的方式调用 console.log(Parent.age); // 18 console.log(Parent.getAge()) // 18
类的继承
与js的继承相似,通常用继承来扩展现有的类。继承之后,子类会拥有父类的一切属性和方法
格式:class 子类 extends 父类
// 创建父类
class Parent {
name: string;
constructor(name: string) {
this.name = name
}
getName() {
return this.name;
}
}
// 创建子类并继承父
class Child extends Parent {
//构造函数
constructor(childName: string) {
super(childName) // 将子类创建时传入的值 给到父构造函数
}
//重写父类方法
override getName(){
console.log('重写了父的getName方法')
}
testFn() {
console.log(this.name)
console.log(this.getName());
}
}
const c = new Child('张三');
c.testFn();
注意点:
- 在构造函数中super()作为方法表示父类的构造函数,super作为对象时,在普通方法中,指向父类的原型对象;
- 如果在子类中写了构造函数,就必须调用父类的构造函数
属性简写形式
// 简写前
class Person {
public name: string
public age: number
constructor(name:string, age:number){
this.name = name
this.age = age
}
}
// 简写后
class Person {
constructor(public name:string, public age:number){}
}
存取器getters/setters
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
class Demo {
// 私有属性外界不能访问,可以通过存取器进行控制
private _name: string;
private _age: number;
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
get name() { // 获取时执行
return this._name;
}
set name(val: string) { // 修改时执行
this._name = val
}
}
const d = new Demo('a',10);
d.name = 'abc'
console.log(d.name)
注意:只带有 get不带有 set的存取器自动被推断为 readonly
抽象类(Abstract)
可以简单理解为用于对类约束的一种方式
抽象类不能实例化(不能被new),其意义是可以被继承,抽象类里可以有普通方法、也可以有抽象方法。
用法👇:
// 定义包裹抽象类
abstract class Package {
// 构造方法
constructor(public weight: number){}
// 运费计算 抽象方法
abstract calculate(): number
// 具体方法
printPackage() {
console.log(`包裹重量为:${this.weight}kg,运费为:${this.calculate()}元`);
}
}
// 定义普通包裹类并继承 包裹抽象类
class StandardPackage extends Package {
constructor(weight: number,public unitPrice: number){
// 调用父的构造方法
super(weight)
}
// 必须具体实现抽象方法
calculate():number {
return this.weight * this.unitPrice
}
}
接口(Interface)
interface 是一种定义结构的方式,主要作用是为:类、对象、函数等规定一种契约,这样可以确保代码的一致性和类型安全,但要注意 interface 只能定义格式,不能包含任何实现 !
说白了也就是对类、对象、函数进行约束限制的一种方式
格式:
interface 接口名 {属性1: 类型1, 属性2: 类型2}
定义类结构
interface IPerson {
// 接口名称(比如,此处的 IPerson),可以是任意合法的变量名称,推荐以 `I`或者PersonInterface 开头
name: string
age: number
speak(n: number): void
}
//定义一个类 Person,需要用 implements 关键字 实现 IPerson 接口
class Person implements IPerson {
constructor(public name: string, public age: number) {}
//实现接口中的 speak 方法,注意:实现speak时参数个数可以少于接口中的规定,但不能多。
speak(n: number): void {
for(let i = 0; i < n; i++){
console.log(`你好,我叫${this.name},我的年龄是${this.age}`)
}
}
}
//创建一个 Person 类的实例 p1,传入名字'tom'和年龄 18
const p1 = new Person('tom', 18)
p1.speak(3)
定义对象结构
interface IUser {
name: string
readonly gender: string // 只读属性
age?: number // 可选属性
run: (n: number) => void
}
const user: IUser = {
name: '张三',
gender: '男',
age: 20,
run(n) {
console.log(`奔跑了${n}米`)
}
}
定义函数结构
interface ICount {
(a: number, b:number): number;
}
const count: ICount = function (x, y) {
return x + y
}
接口继承
如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用
格式:
interface 接口2 extends 接口1 {
属性1: 类型1, // 接口2中特有的类型
}
interface a { x: number; y: number }
// 继承 a
// 使用 extends(继承)关键字实现了接口
interface b extends a {
z: number
}
// 继承后,b 就有了 a 的所有属性和方法(此时,b 同时有 x、y、z 三个属性)
接口和类型别名的区别(面试题)
- 相同点:
interface
和type
都可以用于定义对象结构,两者在许多场景中是可以互换的。 - 不同点:
interface
更专注于定义对象和类的结构,支持继承、合并。type
可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并。
// 接口的写法-------------
interface IPerson {
name: string,
age: number
}
const user1:IPerson = {
name: 'a',
age: 20
}
// type的写法-------------
type Person = {
name: string,
age: number
}
const user2:Person = {
name: 'b',
age: 20
}
接口和抽象类的区别(面试题)
- 相同点:都用于定义一个类的格式(应该遵循的约束)
- 不相同:
1. 接口(interface
):只能描述结构,不能有任何实现代码,一个类可以实现一个或多个接口。
2. 抽象类(abstract
):既可以包含抽象方法,也可以包含具体方法,一个类只能继承一个抽象类。
泛型
就是当类型尚不明确时,可以用类型变量暂时替代,当使用时在明确指定或不指定,TypeScript会根据值进行类型推断,通常用于类、接口和函数 (也就是为了更好的重用)
泛型语法
对于刚接触 TypeScript 泛型的小伙伴来说,首次看到 语法会感到陌生。其实它没有什么特别,就像传递参数一样,我们传递了我们想要用于特定函数调用的类型。
参考上面的图片,当我们调用 identity<number>(1)
,number 类型就像参数 1 一样,它将在出现 T 的任何位置填充该类型。图中 内部的 T 被称为类型变量,它是我们希望传递给 identity 函数的类型占位符,同时它被分配给 value 参数用来代替它的类型:此时 T 充当的是类型,而不是特定的 number 类型。
其中 T 代表 Type,在定义泛型时通常用作第一个类型变量名称。但实际上 T 可以用任何有效名称代替。除了 T 之外,以下是常见泛型变量代表的意思:
- K(Key):表示对象中的键类型;
- V(Value):表示对象中的值类型;
- E(Element):表示元素类型。
注意:泛型类型可以有多个或一个以逗号(,)进行分割,比如<T,…>
function identity <T, U>(value: T, message: U) : T {
console.log(message);
return value;
}
console.log(identity<Number, string>(68, "Semlinker"));
泛型类
泛型应用于类上面
class Person<T>{
private _value: T;
constructor(val: T) {
this._value = val;
}
}
let p = new Person<number>(12)
如上,表示传递一个T类型,在new的时候才把具体类型传入。其中T(Type)是变量可更改,但通常比较常见就是写T,T可以理解成占位符,当进行实例化时传入类型填充此位置
泛型接口
泛型应用在接口上
interface Identities<V, M> {
value: V,
message: M
}
let ident: Identities<number,string> = {
value: 123,
message: '123'
}
泛型函数
泛型应用在函数上
function id<T, U>(arg1: T, arg2: U): T {
return arg1;
}
//调用时传入相应类型,不传ts会根据传入参数进行类型推断
console.log(id<string,number>('1',3)) // "1"
console.log(id('1',3)) // "1"
泛型约束
一般通过extends
方式实现泛型约束
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg:T):T {
return arg;
}
student({name:'lili'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "lili" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});
其他
keyof
该操作符用于获取对象类型的所有键,展开为联合类型(前提对象是类型,如接口,类,type)
type Point = { x: number; y: number };
type P = keyof Point; // 此时的P类型 即为 ‘x’ | ‘y’
type demoType = keyof string // demoType 的类型为"toString" | "charAt" | "charCodeAt" ….
typeof
该操作符可以用来获取一个变量或对象的类型
interface Person {
name: string;
age: number;
}
const sem: Person = { name: 'semlinker', age: 33 };
type Sem= typeof sem; // -> Person
const sem2 = {name:’aaa’,age:12}
type Sem2 = typeof sem2// -> {name:string, age:number}
function toArray(x: number): Array<number> {
return [x];
}
type Func = typeof toArray; // -> (x: number) => number[]
in
该操作符用来遍历枚举类型
type Keys = "a" | "b" | "c"
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any, c: any }
infer
该操作符在有 条件类型 的 extends 子语句中,允许出现 infer 声明,它会引入一个待推断的类型变量。
这个推断的类型变量可以在有条件类型的 true 分支中被引用。
我的理解就是用 infer 定义一个类型变量 接收一个类型 然后用此类型去判断操作
下面通过TypeScript中内置工具类型 ReturnType 理解 infer
ReturnType<T>
– 获取函数返回值类型。
// 此工具类型在ts中的用法
const add = (x:number, y:number) => x + y
type t = ReturnType<typeof add> // type t = number
//ReturnType 工具函数的实现源码
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
再来看 ReturnType 的实现:如果 T 满足约束条件(...args: any) => any
,并且能够赋值给(...args: any) => infer R
,则返回类型为 R
,否则为 any
类型。
.d.ts介绍
类型声明文件是 TypeScript 中的一种特殊文件,通常以 .d.ts 作为扩展名。它的主要作用是为现有的 JavaScript 代码提供类型信息,使得 TypeScript 能够在使用这些 JavaScript 库或模块时进行类型检查和提示。
就是当你在ts中引入js的库或模块时对这个库添加类型提示和检查作用
demo.js
export function add(a, b){
return a + b
}
demo.ts
import { add } from './demo.js'
console.log(add(1, 2))
这里的引入如果不加对应.d.ts文件 会出现红线提示
demo.d.ts
declare
关键字用于ts中声明类型
declare function add(a: number, b: number): number;
export { add }
加上之后 在demo.ts中光标放到add方法上就会有以下提示👇
tsconfig.json
tsconfig.json 是 TypeScript 项目的配置文件。
tsconfig.json 包含 TypeScript 编译的相关配置,通过更改编译配置项,我们可以让 TypeScript 编译出 ES6、ES5、node 的代码。
使用命令生成
tsc --init
重要字段
- files - 设置要编译的文件的名称;
- include - 设置需要进行编译的文件,支持路径模式匹配;
- exclude - 设置无需进行编译的文件,支持路径模式匹配;
- compilerOptions - 设置与编译流程相关的选项。
compilerOptions 选项
{
"compilerOptions": {
/* 基本选项 */
"target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"lib": [], // 指定要包含在编译中的库文件
"allowJs": true, // 允许编译 javascript 文件
"checkJs": true, // 报告 javascript 文件中的错误
"jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
"declaration": true, // 生成相应的 '.d.ts' 文件
"sourceMap": true, // 生成相应的 '.map' 文件
"outFile": "./", // 将输出文件合并为一个文件
"outDir": "./", // 指定输出目录
"rootDir": "./", // 用来控制输出目录结构 --outDir.
"removeComments": true, // 删除编译后的所有的注释
"noEmit": true, // 不生成输出文件
"importHelpers": true, // 从 tslib 导入辅助工具函数
"isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"strictNullChecks": true, // 启用严格的 null 检查
"noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
"alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)
/* 模块解析选项 */
"moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"baseUrl": "./", // 用于解析非相对模块名称的基目录
"paths": {}, // 模块名到基于 baseUrl 的路径映射的列表
"rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
"typeRoots": [], // 包含类型声明的文件列表
"types": [], // 需要包含的类型声明文件名列表
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
/* Source Map Options */
"sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
"mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
"inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
"inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性
/* 其他选项 */
"experimentalDecorators": true, // 启用装饰器
"emitDecoratorMetadata": true // 为装饰器提供元数据的支持
}
}
到这里就结束了,后续还会更新 vue 系列相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!
推荐文章👇
ts保姆级教程,别再说你不会ts了
你不知道的 TypeScript 泛型(万字长文,建议收藏)
接近天花板的TS类型体操,看懂你就能玩转TS了
TypeScript中的never类型具体有什么用?
理解 TypeScript 类型收窄