嘟嘟嘟在線觀看播放免費寧波seo外包推廣平臺
TypeScript學習總結(jié)內(nèi)容目錄:
- TypeScript概述 TypeScript特性。
- Javascript與TypeScript的區(qū)別
????* TypeScript安裝及其環(huán)境搭建- TypeScript類型聲明
???? * 單個類型聲明,多個類型聲明
???? * 任意類型聲明
????* 函數(shù)類型聲明
???? * unknown類型【未知類型】
????* 對象類型聲明
???? * 數(shù)組類型聲明
???? * 元組
???? * 枚舉- TypeScript編譯選項
????* 自動編譯文件
???? * 自動編譯整個項目- webpack打包TS代碼
???? * 配置打包命令
???? * 創(chuàng)建build文件夾里面webpack.config.js配置- TypeScript面向?qū)ο?
????* 定義類
????* 修飾符
????* 方法重載
????* 抽象類
????* 接口
???? * 擴展接口- 類裝飾器
- 映射類型
- 條件類型
TypeScript概述
TypeScript是JavaScript的一個超集,支持ECMAScript 6 ES6標準,TypeScript設(shè)計目標是開發(fā)大型應(yīng)用,它可以編譯成純Javascript,編譯出來的Javascript可以運行在任何瀏覽器上。
TypeScript特性。
TypeScript是一種給JavaScript添加特性的語言擴展,增加一下功能,類型批注和編譯時類型檢查,類型推斷,類型擦除,接口,枚舉,Mixin,泛型編程,名字空間,元組,Await,和沖ECMA2015移植過來的,類,模塊,lambda函數(shù)的箭頭語法,可選參數(shù)以及默認參數(shù)。
Javascript與TypeScript的區(qū)別
TypeScript是Javascript的超集,擴展了JavaScript的語法,因此現(xiàn)有的Javascript代碼可以與TypeScript一起工作無需任何更改,TypeScript通過類型注解提供編譯時靜態(tài)類型檢查,TypeScript可處理已有的JavaScript代碼,并只對其中的TypeScript代碼進行編譯。
TypeScript安裝及其環(huán)境搭建
-
下載Node.js 并 安裝Node.js
【下載NodeJS】
一直”next“
一直"next"
![TypeScript安裝及其環(huán)境搭建]](https://img-blog.csdnimg.cn/931c7af0b93d4d729faf544f5119ab29.png)
選擇安裝路徑
搭建完成~
-
使用全局安裝typeScript
安裝完成以后,接著輸入命令
查看typescript編譯器的版本信息,代表安裝成功 -
創(chuàng)建一個ts文件并運行
nodePad++ 安裝包
鏈接: https://pan.baidu.com/s/1YTb2NNK7HQ6YELlIxms0mg?pwd=3s8v 提取碼: 3s8v
復(fù)制這段內(nèi)容后打開百度網(wǎng)盤手機App,操作更方便哦
使用tsc new.ts 生成一個.js文件
使用 node new.ts 運行ts文件
TypeScript類型聲明
強類型定義語言在數(shù)度上可能略遜色于弱類型定義語言,但是強類型定義語言帶來的嚴謹性能夠有效的避免許多錯誤。
- 單個聲明類型、多個類型聲明
//單個聲明類型var [變量名] : [類型];var a: let a:number; //多個類型聲明var [變量名]:[類型1]|[類型2]let c:boolean|string;c = truec = "hello"
- 任意類型聲明
//任意類型,如果不指定類型,則ts解析器會自動判斷變量的類型為any(隱式的any)//方式一、var [變量名] = 值;//方式二、let [變量名] :[any]let d:any; //任何類型d = 1;d = "1"d = true;
- 函數(shù)類型聲明
// 函數(shù)類型function sum(a:number,b:number):number{//a,b只能是number類型,返回類型必須是number}function sum(a:number,b:number):number:boolen{//返回值類型可以說number或者boolen}//沒有返回值函數(shù)function fun():void{/** viod 標識空,沒有返回值,如果寫return 會報錯* 可以返回null,undefined*/}// 永遠都不會返回結(jié)果function fun():never{throw new Error("error")//never表示永遠不會返回結(jié)果,會報錯}//設(shè)置函數(shù)結(jié)構(gòu)的類型聲明 希望d是函數(shù),a,b是number,返回類型numberlet d:(a:number,b:number)=>numberd = function(a:number,b:number):number{return a + b}
- unknown類型【未知類型】
//unknown類型,unknow類型變量不能隨便賦值給其他變量,let e:unknowne=10;e="hellow";e=true;let a:string;a=e; //unknow類型,賦值給其它會報錯//如果真的想賦值,可以通過如下方式if(typeof(e)==="string"){a = e}//或者通過類型斷言:高數(shù)解析器變量的實際類型,跳過報錯a = e as stringa = <string>e
- 對象類型聲明
// {}用來指定對象中可以包含哪些屬性let b:{name:string,age?:number //加一個問好代表這個屬性可有可無,可選屬性}b = {name:"張三",age:18}b = {name:"張三"}// name必填,[prop:string]:any 任意類型的屬性let c:{name:string,[prop:string]:any}c = {name:"李四",a:1,b:2,c:"aaaa"};
- 數(shù)組類型聲明
//格式// Array<類型>// string[]表示字符串數(shù)組let arr:string[];arr = ['a','b','c']//數(shù)值類型let arr2:Array<number>arr2 = [1,2,3]
- 元組
元組,元素就是固定長度的數(shù)組語法: [類型,類型,類型]let h : [string,string]h = ["1","2"]
- 枚舉
//所有可能情況列舉出來enum Gender{Male = 0,Fenake = 1}let i : {name:string,gender:Gender}i={name:"孫悟空",gender:Gender.male}console.log(i.gender === Gender.Male)// &表示同時滿足類型let j : {name:string} & {age:number}//類型別名 簡化類型的使用type myType = 1|2|3|4|5;let k : myType;let l : myType;let m : myType;
TypeScript編譯選項
-
自動編譯文件
編譯文件時,使用-w指令后,ts編譯器會自動監(jiān)視文件的變化,并在文件發(fā)生變化的時候?qū)ξ募M行重新編輯。
tsc xxx.ts -w
-
自動編譯整個項目
tsc
但是,使用tsc的前提,是要在項目根目錄下創(chuàng)建一個ts的配置文件 tsconfig.json,添加完成后,只需要tsc命令就可以對整個項目的ts文件進行編譯。
tsconfig.json是ts編譯器的配置文件,可以根據(jù)他的信息可以對代碼進行編譯。配置如下
1. “include”:用來指定哪些ts文件需要編譯
???? ** 表示任意目錄
????* 表示任意文件
????例如:“include”:[“./src/**/*”]
2. “exclude” 不需要被編譯的文件目錄????例如:“exclude”:[".src/hello/**/“]
3.“extends” 繼承 其他的配置文件
????*例如:“extends”:”./config/base"
4.“files” 用來指定被編譯的文件的列表,只需要編譯的文件少時才會用到。
????“files”:[
????????“code.te”,
????????“hellow.ts”,
????????“binder.ts”
????]
5.“compilerOptions” 編譯選項是配置文件中非常重要也比較復(fù)雜的配置選項,在compilerOptions中包含了許多哥子選項,用來完成對編譯器的配置。
“compilerOptions”:{
???????“target”:“ES6”, //通設(shè)定ts被編譯的ES的版本
???????“module”:“commonjs”, //指定要使用的模塊化的規(guī)范
???????“l(fā)ib”:[“dom”], //用來指定項目中的要使用的庫
???????“outDir”:“./dist”, //用來指定編譯后文件所在的目錄
???????“outFile”:“./dist/app.js”, //將代碼合并成一個文件,設(shè)置outFile后,所有的全局作用域中的代碼會合并到同一個文件中
???????“allowJs”:false, //是否對JS文件進行編譯,默認是false
???????“checkJs”:false, //是否檢查JS代碼符合語法的規(guī)范,默認是false
???????“removeComments”:true, //編譯時候是否移除注釋
???????“noEmit”:false, //不生成編譯后的文件
???????“noEmitError”:true, //當有錯誤時候不生成編譯后的文件
???????“alwaysStrict”:false, //用來設(shè)置編譯后的文件是否使用嚴格模式,默認false
???????“noImplicitAny”:false //不允許隱式的數(shù)據(jù)類型
}
添加tsconfig.json文件
可以使用tsc或者tsc -w進行運行,生成js文件,
WebPack打包TS代碼
- 首先下載依賴,在集成終端打開后:
npm init -ytsc --init 產(chǎn)生對應(yīng)的ts.config.js文件npm install -D typescriptnpm install -D webpack@4.41.5 webpack-cli@3.3.10npm install -D webpack-dev-server@3.10.2 啟動開發(fā)服務(wù)器的npm install -D html-webpack-plugin@4.0.0-alpha clean-webpack-plugin 對html內(nèi)容進行打包 / 清除之前打包好的js文件npm install -D ts-loader@8.0.11 針對ts文件進行編譯處理npm install -D cross-env 涉及跨平臺命令
- 配置打包命令:
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js","build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
- 創(chuàng)建build文件夾里面webpack.config.js配置如下:
const {CleanWebpackPlugin} = require('clean-webpack-plugin')const HtmlWebpackPlugin = require('html-webpack-plugin')const path = require('path')const isProd = process.env.NODE_ENV === 'production' // 是否生產(chǎn)環(huán)境function resolve (dir) {return path.resolve(__dirname, '..', dir)}module.exports = {mode: isProd ? 'production' : 'development', //模式:生產(chǎn)模式還是開發(fā)模式entry: {app: './src/main.ts' //程序主入口目錄},output: {path: resolve('dist'), //將打包好的文件放到dist目錄里面filename: '[name].[contenthash:8].js' //產(chǎn)生的js文件是以app加上8位的哈希值.js來命名的},module: {rules: [ //rules主要是通過ts-loader這個包針對于ts文件,針對src目錄里面的ts和tsx文件進行編譯處理操作{test: /\.tsx?$/,use: 'ts-loader',include: [resolve('src')]}]},plugins: [new CleanWebpackPlugin({ //會將dist目錄中以前打包的js文件進行清楚}),new HtmlWebpackPlugin({ //針對于./public/index.html進行打包的template: './public/index.html'})],resolve: {extensions: ['.ts', '.tsx', '.js'] //針對于'.ts', '.tsx', '.js'這三種文件進行處理引入文件可以不寫他的擴展名},//針對于代碼的錯誤提示devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',devServer: {host: 'localhost', // 主機名stats: 'errors-only', // 打包日志輸出輸出錯誤信息port: 8081, //端口open: true //自定打開瀏覽器},}
- 最后創(chuàng)建src目錄下的main.ts:
document.write('Hello Webpack TS!') npm run dev后在主頁面中成功查看hellowebpackTS就說明成功運行
TS面向?qū)ο?/h2>
- 定義類
class 類名 {屬性名: 類型;constructor(參數(shù): 類型){this.屬性名 = 參數(shù);}方法名(){....}
}
- 修飾符
static 靜態(tài)屬性,通過類即可直接使用,不能被子類共享
readonly 只讀屬性無法修改
public 默認值,可以在類、子類和對象中修改
protected 可以在類、子類中修改
private 可以在類中修改
constructor(public name: string, public age: number) {} 可以直接將屬性定義在構(gòu)造函數(shù)中://語法糖:name: string;age: numberconstructor(name: string, age: number) {this.name = name;this.age = age;}//Singleton 類class Order {count: number = 0private static instanceRef: Orderprivate constructor() { }static getInstance(): Order {if (Order.instanceRef === undefined)Order.instanceRef = new Order()return Order.instanceRef}}// const order = new Order()=> 構(gòu)造函數(shù)是私有的,僅可在類聲明中訪問。const order1 = Order.getInstance()const order2 = Order.getInstance()order1.count++; order2.count++;console.log(order1.count) //2console.log(order2.count) //2
//----------------------------------Order有一個private構(gòu)造函數(shù),不能用new實例化 Order,在 static getInstance()中完成調(diào)用該類構(gòu)造函數(shù),這是調(diào)用該方法的唯一途徑,兩次 console.log 都是打印 2,因為只有一個 Order 的實例。若想創(chuàng)建一個自身不能被實例化而子類能被實例化的類時,可以用 protected 修飾構(gòu)造函數(shù)。class OrderItem extends Order {pid: stringconstructor(pid: string, count: number) {super()this.productid = productid}}
- 方法重載
聲明多個同名的方法,但只能統(tǒng)一實現(xiàn),結(jié)合條件判斷,使用 | 表明多個類型的返回值。若聲明方法的代碼去掉,代碼仍然正常運行,或者干脆設(shè)置不同的方法名。
重載目的:提供從參數(shù)類型到返回值類型的合適的映射。
應(yīng)用場景:重載構(gòu)造函數(shù)。
重構(gòu)構(gòu)造函數(shù) < = > 用接口表示可能的參數(shù) obj,constructor(properties?: 接口名){}
class Product {getProducts(): voidgetProducts(id: number): voidgetProducts(id?: number): void {if (typeof id == 'number'){console.log(`Getting the product info for ${id}`)}else {console.log('Getting all products')}}
}
class 類名 {屬性名: 類型;constructor(參數(shù): 類型){this.屬性名 = 參數(shù);}方法名(){....}
}
static 靜態(tài)屬性,通過類即可直接使用,不能被子類共享
readonly 只讀屬性無法修改
public 默認值,可以在類、子類和對象中修改
protected 可以在類、子類中修改
private 可以在類中修改
constructor(public name: string, public age: number) {} 可以直接將屬性定義在構(gòu)造函數(shù)中://語法糖:name: string;age: numberconstructor(name: string, age: number) {this.name = name;this.age = age;}//Singleton 類class Order {count: number = 0private static instanceRef: Orderprivate constructor() { }static getInstance(): Order {if (Order.instanceRef === undefined)Order.instanceRef = new Order()return Order.instanceRef}}// const order = new Order()=> 構(gòu)造函數(shù)是私有的,僅可在類聲明中訪問。const order1 = Order.getInstance()const order2 = Order.getInstance()order1.count++; order2.count++;console.log(order1.count) //2console.log(order2.count) //2
//----------------------------------Order有一個private構(gòu)造函數(shù),不能用new實例化 Order,在 static getInstance()中完成調(diào)用該類構(gòu)造函數(shù),這是調(diào)用該方法的唯一途徑,兩次 console.log 都是打印 2,因為只有一個 Order 的實例。若想創(chuàng)建一個自身不能被實例化而子類能被實例化的類時,可以用 protected 修飾構(gòu)造函數(shù)。class OrderItem extends Order {pid: stringconstructor(pid: string, count: number) {super()this.productid = productid}}
聲明多個同名的方法,但只能統(tǒng)一實現(xiàn),結(jié)合條件判斷,使用 | 表明多個類型的返回值。若聲明方法的代碼去掉,代碼仍然正常運行,或者干脆設(shè)置不同的方法名。
重載目的:提供從參數(shù)類型到返回值類型的合適的映射。
應(yīng)用場景:重載構(gòu)造函數(shù)。
重構(gòu)構(gòu)造函數(shù) < = > 用接口表示可能的參數(shù) obj,constructor(properties?: 接口名){}
class Product {getProducts(): voidgetProducts(id: number): voidgetProducts(id?: number): void {if (typeof id == 'number'){console.log(`Getting the product info for ${id}`)}else {console.log('Getting all products')}}
}
運行效果:
抽象類是專門用來被其他類所繼承的類,它只能被其他類所繼承不能用來創(chuàng)建實例。
抽象方法,抽象方法沒有方法體只能定義在抽象類中,繼承抽象類時抽象方法必須要實現(xiàn)
abstract class Animal{abstract run(): void;bark(){console.log('動物在叫~');}
}
class Dog extends Animals{run(){console.log('狗在跑~');}
}
- 接口
再JS中并沒有接口概念,接口interface通俗的來說就是對類中的屬性和方法進行統(tǒng)一的類型聲明,哪個類調(diào)用此接口,在一般情況下具有接口中相應(yīng)的類型聲明的屬性和方法,接口中的屬性和方法名后添加表示屬性或方法是可選項,調(diào)用接口的類中可以根據(jù)具體的需要進行聲明,一個類可以實現(xiàn)多個接口的調(diào)用,不同的接口用逗號隔開,需要注意的是,接口中聲明的方法默認是抽象方法,也就是不具備方法體,需要我們調(diào)用接口的時候進行方法重寫。
type myType = {name: string,age: number};const obj: myType = {name: 'sss',age: 111};
Interface myInterface {name: string;age: number;}const obj: myInterface = {name: 'sss',age: 111 };
上面代碼中,進行了type和interface的比較
不能創(chuàng)建多個同名type,但是可以創(chuàng)建多個同名接口,采取合并策略。
接口用來定義一個類的結(jié)構(gòu),該類應(yīng)該包含的屬性/方法(不能同時),也可以當成類型聲明。
接口只定義對象的結(jié)構(gòu),不考慮實際值。
在接口中,所有的屬性都不賦實際值,所有的方法都是抽象方法。
不能在聯(lián)合或交叉中使用接口類。
interface Person {age: number}interface Customer {n ame: string}type cust = Person | Customer √interface cust = Person | Customer ×
- 接口實現(xiàn)
一個類可以實現(xiàn)多個接口,用逗號隔開
class MyClass implements myInter{constructor(public name: string) {this.name = name;}sayHello(){console.log('大家好~~');}}
- 擴展接口
interface B extends A{聲明 B 新增的方法}
- getter 和 setter
在類中定義一組讀取 getter、設(shè)置屬性 setter 的方法,被稱為屬性的存取器。
private _name: string;private _age: number;constructor(name:string, age: number) {this._name = name;this._age = age;}get name(){return this._name;}set name(value: string){this._name = value;}get age(){return this._age;}set age(value: number){if(value >= 0){this._age = value}}
此時可以修改 per.name = ‘豬八戒’; per.age = -33;否則若為定義存取器,會報錯。
- 泛型
(1),繁星差異:當x類可用,就可使用與X類兼容的其他對象或子類,即泛型差異適用于結(jié)構(gòu)相同的對象。
(2),不指定泛型,TS可以自動對類型進行推斷。
(3),泛型可以同時指定多個,一般 T 表示類型,K 表示鍵,V 表示值。function fn<T>(a: T): T{ //=> 箭頭函數(shù):const fn = <T>(a: T):T =>{……}return a;}fn('huahua') //自動識別為string
(4),T extends Inter 表示泛型 T 必須是 Inter 實現(xiàn)類(子類)function fn2<T, K>(a: T, b: K):T{console.log(b);return a; } fn2<number, string>(123, 'hello');
(5),類和接口中同樣可以使用泛型interface Inter{ length: number }function fn3<T extends Inter>(a: T): number{return a.length;}
? 調(diào)用使用泛型的類或接口時,必須指定類型,若不確定類型 →
? Solve:any 類型,extends A 或 > 聲明默認參數(shù)類型 class A <T = any> 啞元類型,class A < T= {}>
? 實例——接口用于比較矩形大小和員工工資。
實例——接口用于比較矩形大小和員工工資。
interface Comparator<T> {compareTo(value: T): number;}class Rt implements Comparator<Rt>{constructor( private width: number, private height: number){}compareTo(value: Rt): number {return this.width * this.height - value.width * value.height}}class Pg implements Comparator<Pg>{constructor( public name: string, private salary: number) {}compareTo(value: Pg): number {return this.salary - value.salary;}}const rect1: Rect = new Rect(2, 5);const rect2: Rect = new Rect(2, 3);rect1.compareTo(rect2)>0?console.log("rect1 is bigger"):(rect1.compareTo(rect2)== 0 ? console.log("rects are equal") :console.log("rect1 is smaller"))const prog1: Pg = new Pg("John", 20000);const prog2: Pg = new Pg("Alex", 30000);prog1.compareTo(prog2) > 0 ?console.log(`${prog1.name} is richer`) :prog1.compareTo(prog2) == 0 ? console.log(`earn the same amounts`) : console.log(`${prog1.name} is poorer`)
類裝飾器
(1) 參數(shù)——類的構(gòu)造函數(shù)
(2) 類裝飾器返回類型為 void,不會替換類聲明(觀察類)。返回新函數(shù),會修改構(gòu)造函數(shù)。
Eg:觀察類function whoAmI (target: Function): void{console.log(`You are: ${target} `)}@whoAmIclass Friend {constructor(private name: string, private age: number){}}
觀察類 2function UIcomponent (html: string): Funcion {console.log(`The decorator received ${html} \n`);return function(target: Function) {console.log(`A UI component from \n ${target}`)}}@UIcomponent('<h1>Hello Shopper!</h1>')class Shopper {constructor(private name: string) {}}
(3)修改類聲明的裝飾器:
// 使用類型 any[]的 rest 參數(shù),可以混合其他有構(gòu)造函數(shù)的類
type constructorMixin = { new(...args: any[]): {} };
function useSalutation(salutation: string) {return function <T extends constructorMixin>(target: T) {return class extends target {name: stringprivate message = 'Hello ' + salutation + this.namesayHello() { console.log(`${this.message}`); }}}
}// 運行時 tsc ***.ts --target ES5 -w --experimentalDecorators@useSalutation("Mr. ")class Greeter {constructor(public name: string) { }sayHello() { console.log(`Hello ${this.name}`) };}const grt = new Greeter('Smith');grt.sayHello(); => Hello Mr. Smith
(4)函數(shù)裝飾器
(1) target 引用定義函數(shù)的實例類的對象propertyKey 被裝飾的函數(shù)的名稱descriptor 被裝飾的函數(shù)的標識符,含一個 value 屬性,存儲被裝飾函數(shù)的原始代碼。修改該屬性,可以修改被裝飾函數(shù)的原始代碼。function logTrade(target, propertyKey, descriptor) {descriptor.value = function () {console.log(`Invoked ${propertyKey} providing:`, arguments);}}class Trade {@logTradeplaceOrder(stockName: string, quantity: number, operation: string, tradedID: number) {}}const trade = new Trade();trade.placeOrder('IBM', 100, 'Buy', 123);=> Invoked placeOrder providing: [Arguments] {'0':'IBM','1':100,'2':'Buy','3': 123}
(5)執(zhí)行順序
屬性 > 方法 > 方法參數(shù) > 類,多個同樣的裝飾器,它會先執(zhí)行后面的裝飾器。
// 類裝飾器
function anotationClass(id) {console.log('anotationClass evaluated', id);return (target) => console.log('Class executed', id);
}
// 方法裝飾器function anotationMethods(id) {console.log('anotationMethods evaluated', id);return (target, property, descriptor) => console.log('Methods executed', id);}@anotationClass(1)@anotationClass(2)class Example {@anotationMethods(1)@anotationMethods(2)method() { }}// Methods evaluated 1// Methods evaluated 2// Methods executed 2// Methods executed 1// Class evaluated 1// Class evaluated 2// Class executed 2// Class executed 1
映射類型
1.Readonly:只讀映射類型,將先前聲明的類型的所有屬性都調(diào)整為 Readonly。
原理 :type Readonly<T> = { //索引類型查詢,表示屬性名的聯(lián)合Readonly [P in keyof T]: T[P] //表示將給定類型 T 的所用屬性聯(lián)合給 P,T[p]是查詢類型,表示類型為 T[p]的屬性。} Eg:interface Person {name: stringage: number}type propNames = keyof Person // type propNames = "name"|"age"type propTypes = Person[propNames] // type propTypes = string | numberconst worker: Person = { name: 'John', age: 22 }function doStuff(person: Readonly<Person>) {person.age = 25 =>無法分配到 "age" ,因為它是只讀屬性。}keyof 和 T[p] 應(yīng)用interface Person {name: string;age: number;}const persons: Person[] = [{ name: 'John', age: 32 },{ name: 'Mary', age: 33 },];function filterBy<T, P extends keyof T>(property: P,value: T[P],array: T[]) {return array.filter(item => item[property] === value);}console.log(filterBy('name', 'John', persons));console.log(filterBy('lastName', 'John', persons)); // errorconsole.log(filterBy('age', 'twenty', persons)); // error
2.Partial:
//所有屬性可選,原理 →type Partial<T> = {[P in keyof T]?: T[P]}
3.Required
//所有屬性都必須,原理 →type Required<T> = {[P in keyof T]-?: T[P]}
4.Pick
//選擇給定類型屬性的子集聲明新類型type Pick<T, K extends keyof T> ={[P in K]: T[P]}
5.多個映射類型
Readonly<Partial<Person>>
6.自定義
type Modifiable<T> = {-readonly [P in keyof T]: T[P]}type NewPromise<T> = T extends (...args: infer A) =>infer R ? (...args: A) => Promise<R> : T;type Promisify<T> = {[P in keyof T]: NewPromise<T[P]>}
條件類型
1.T extends U ? X : Y
含義:檢查是否 T 可以分配給 U,如果為真,則使用類型 X,否則使用類型 Y。
2.Exclude 類型
原理: type Exclude<T, U> = T extends U ? never : T 含義:若果 T 不能分配給
U,這保留它,否則過濾掉它。 Eg:刪除 Person 類型中的 name 和 age 屬性。
class Person {id: number;name: string;age: number;
}
type RemoveProps<T, K> = Exclude<keyof T, K>
type RemainingProps = RemoveProps<Person, 'name' | 'age'>;
<=> 'id' | 'name' | 'age' extends 'name' | 'age' ? never : 'id' | 'name' | 'age' <=> RemainingProps = 'id'
type PersonBlindAuditions = Pick<Person, RemainingProps>;
<=> 表示 Person 類屬性子集的聯(lián)合被重新聲明新類型
<=> 結(jié)果 type PersonBlindAuditions = { id: number}
3.infer 關(guān)鍵字
type ReturnType = T extends (…args: infer A) => infer R ?
含義:該類型是一個函數(shù),參數(shù)為任意數(shù)量的 infer A 類型,返回值為 infer R 類型。 應(yīng)用:將類中的方法轉(zhuǎn)化為異步方法
interface SyncService {baseUrl: string;getA(): string;}type ReturnPromise<T> =T extends (...args: infer A) => infer R ? (...args: A) => Promise<R> : T;type Promisify<T> = {[P in keyof T]: ReturnPromise<T[P]>;};class AsyncService implements Promisify<SyncService> {baseUrl: string;getA(): Promise<string> {return Promise.resolve('');}}let service = new AsyncService();let result = service.getA(); // hover answer——let result: Promise<string>