摘要:空類型,一般用來表示函數(shù)沒有返回值。返回值的類型則跟在參數(shù)的括號(hào)后面,冒號(hào)后面跟一個(gè)返回值的類型。箭頭函數(shù)參數(shù)與返回值的聲明方法與普通函數(shù)無二。函數(shù)重載當(dāng)一個(gè)函數(shù)在入?yún)⒉煌瑫r(shí)有較大的行為差距時(shí),可以使用函數(shù)重載梳理代碼結(jié)構(gòu)。
類型系統(tǒng)是 typescript 最吸引人的特性之一,但它的強(qiáng)大也讓我們又愛又恨,每個(gè)前端同學(xué)在剛從 javascript 切換到 typescript 時(shí)都會(huì)有一段手足無措的時(shí)光,為了不讓編譯器報(bào)錯(cuò)恨不得把所有變量都標(biāo)注成 any 類型,而后在不斷地填坑中流下悔恨的淚水。Change Log 2018-11-14謹(jǐn)以此文記錄我在學(xué)習(xí) typescript 類型系統(tǒng)使用方法的過程中遇到的一些問題,以供大家參考,避免大腦進(jìn)水。
(本文默認(rèn)所有讀者熟知活動(dòng)所有 ES6 語法及特性)
改正了枚舉與 .d.ts 文件的說明
2018-11-13修正了 .d.ts 一節(jié)中 class 在 .d.ts 文件中定義時(shí)使用了 export default 語法的問題
增加了 .d.ts 文件的使用注意事項(xiàng)
增加了枚舉(enum)不能定義在 .d.ts 文件中的說明
增加了枚舉(enum)部分對(duì)于為什么要使用 type xxx = "a" | "b" 來替換枚舉進(jìn)行了說明
0x00 無知 類型聲明 基礎(chǔ)類型直接將類型附在變量聲明之后,并以冒號(hào)分隔。
const count: number = 3; const name: string = "apples"; const appleCounts: string = count + name; assert.strictEqual(appleCounts, "3apples");引用類型
稍微復(fù)雜一點(diǎn)的,如數(shù)組 & 對(duì)象,按照其內(nèi)成員結(jié)構(gòu)進(jìn)行聲明。
const object: { a: number } = { a: 1, }; const array1: number[] = [1,]; const array2: Array函數(shù)類型= [2,];
寫法極像箭頭函數(shù)。
const someFn: (str: string) => number = function (str: string) { return +str; }typescript 擴(kuò)展的輔助類型 any
啥都能放,但并不建議大量使用,如果所有變量都是 any,那 typescript 跟 javascript 又有什么區(qū)別呢。
const variable: any = "5";void
空類型,一般用來表示函數(shù)沒有返回值。
function someFn (): void { 1 + 1; }類型并聯(lián)
當(dāng)一個(gè)變量可能是多種類型時(shí),使用 | 進(jìn)行多個(gè)不同類型的分隔:
const nos: number | string = "1";在引用類型中使用
錯(cuò)誤用法
一定,一定,一定 不要用 , 作分隔符。
const object: { a: [number, string] } = { a: 1, };
正確用法
const object: { a: number | string } = { a: 1, }; const array1: (number | string)[] = [ 1, ]; const array2: Array= [ 2, ];
或
type numberOstring = number | string; const object: { a: numberOstring } = { a: "yes", }; const array1: numberOstring[] = [ "yes", ]; const array2: Array在函數(shù)入?yún)?& 出參中聲明類型= [ "yes", ];
函數(shù)的入?yún)㈩愋透暶髯兞康念愋蜁r(shí)差不多,直接在變量名后跟類型名稱就可以了。
返回值的類型則跟在參數(shù)的括號(hào)后面,冒號(hào)后面跟一個(gè)返回值的類型。
function someFn (arg1: string, arg2: number): boolean { return +arg1 > arg2; }箭頭函數(shù)
參數(shù)與返回值的聲明方法與普通函數(shù)無二。
setTimeout((): void => { console.log("six six six"); }, 50);在類中聲明類型
實(shí)例屬性記得一定要初始化。
class SomeClass { a: number = 1; b: string; static a: boolean; constructor () { this.b = "str"; } method (str: string): number { return +str; } }類型轉(zhuǎn)換
當(dāng)你在聲明一個(gè)普通的對(duì)象(其他類型也有可能,此處僅使用對(duì)象作為例子)時(shí),typescript 并不會(huì)自動(dòng)為你添加上對(duì)應(yīng)的類型,這會(huì)造成你在賦值時(shí)觸發(fā) TS2322: Type "xxx" is not assignable to type "xxx". 錯(cuò)誤,此時(shí)就需要使用顯式類型轉(zhuǎn)換來將兩邊的類型差異抹平。
類型轉(zhuǎn)換的前提是當(dāng)前類型是真的可以轉(zhuǎn)換為目標(biāo)類型的,任何必選屬性的缺失,或是根本無法轉(zhuǎn)換的類型都是不允許的。
并不推薦這種方法,因?yàn)橛袝r(shí)編輯器會(huì)把它當(dāng)成 jsx 處理,產(chǎn)生不必要的 warning。
const object1: object = { a: 1, }; const object2: { a: number } = <{ a: number }>object1;as 表達(dá)式轉(zhuǎn)換
const object1: object = { a: 1, }; const object2: { a: number } = object1 as { a: number };0x01 理智 自定義類型
相當(dāng)于聯(lián)結(jié)多個(gè)不同類型,并為他們創(chuàng)造一個(gè)假名,平時(shí)寫多個(gè)類型并聯(lián)實(shí)在是太累了的時(shí)候可以試試這個(gè)方法。
它的值可以是類型,也可以是具體的變量值。
type NumberOrString = number | string; type Direction = "Up" | "Right" | "Down" | "Left"; const num: NumberOrString = 1; const dir: Direction = "Up";枚舉 官方
注意:枚舉內(nèi)部賦值時(shí)如果為數(shù)字,可以只賦值第一個(gè),后面幾個(gè)會(huì)隨之遞增,如果為字符串,則需要全部賦值,否則就會(huì)報(bào)錯(cuò)。
enum Direction { Up = 1, Right, Down, Left } const dir: Direction = Direction.Up;我的方法
如果你的代碼中準(zhǔn)備使用 enum 作為右值,那請(qǐng)不要把 enum 聲明在 .d.ts 文件中,這是因?yàn)?ts 在編譯的時(shí)候 .d.ts 文件是作為類型文件用的,并不會(huì)生成實(shí)體輸出,自然也就沒有地方會(huì)定義這個(gè)枚舉,這個(gè)時(shí)候用在代碼里作為右值的枚舉值就會(huì)因?yàn)檎也坏秸麄€(gè)枚舉的定義,從而觸發(fā) "xxx is undefined" 錯(cuò)誤。
這也使得它在使用過程中給我們?cè)斐闪烁鞣N各樣的麻煩(在 .d.ts 的 interface 聲明中使用 enum 真的是再正常不過的事情了),比如:
// my-types.d.ts declare const enum Direction { Up = 0, Right = 1, Down = 2, Left = 3, }
// usage.ts class SomeClass { dir = Direction.Up; }
編譯后的結(jié)果是:
// .d.ts 文件當(dāng)場消失
// usage.js function SomeClass () { this.dir = Direction.up; }
瀏覽器在運(yùn)行時(shí)根本找不到 Direction 定義的位置,自然就報(bào) "Direction" is not defined 的錯(cuò)了,但 type Direction = "Up" | "Right" | "Down" | "Left" 的方法就不會(huì)有這種問題,具體使用方式如下:
// my-types.d.ts type Direction = "Up" | "Right" | "Down" | "Left";
// usage.ts const dir: Direction = "Up";
缺點(diǎn)是沒有類型提示,不能定義枚舉的內(nèi)部值,判斷的時(shí)候也必須用對(duì)應(yīng)的字符串進(jìn)行字符串比對(duì)(汗。
接口 基礎(chǔ)聲明一種類型的對(duì)象,該類型的變量都必須滿足該結(jié)構(gòu)要求。
interface SomeInterface { str: string; num: number; } const object: SomeInterface = { str: "str", num: 1, }; class SomeClass implements SomeInterface { num = 1; constructor () { this.str = "str"; } }多重實(shí)現(xiàn)
同一個(gè)類可以實(shí)現(xiàn)多個(gè)不同的接口,但前提是該類一定要實(shí)現(xiàn)每個(gè)接口所要求的屬性。
interface Interface1 { str: string; } interface Interface2 { num: number; } class SomeClass implements Interface1, Interface2 { num = 1; constructor () { this.str = "str"; } }聲明合并
在多個(gè)不同文件,或是相同文件的不同位置聲明的同名接口,將會(huì)被合并成一個(gè)接口,名稱不變,成員變量取并集。
interface SomeInterface { str: string; } interface SomeInterface { num: number; } // 必須全部實(shí)現(xiàn) const someInterface: SomeInterface = { str: "str", num: 1, };函數(shù)接口 基礎(chǔ)使用
interface InterfaceFn { (str: string): boolean; } const fn1: InterfaceFn = (str: string): boolean => { return 10 < str.length; };當(dāng)該類函數(shù)還具有成員變量和方法時(shí)
interface InterfaceFn { (str: string): boolean; standard: string; someFn(num: number): string; } // 必須進(jìn)行顯式類型轉(zhuǎn)換 let fn1: InterfaceFn = function (str: string): boolean { return 10 < str.length; } as InterfaceFn; fn1.standard = "str"; fn1.someFn = function (num: number): string { return `${num}`; };繼承
接口可以繼承類或是另一個(gè)接口,與 ES6 繼承方法語法一樣,在此不再贅述。
函數(shù) & 接口的缺省值及可選項(xiàng)當(dāng)該參數(shù)為可選項(xiàng)時(shí),可以在名稱與類型表達(dá)式的冒號(hào)之間加一個(gè)問號(hào) ? 用來表示該參數(shù)為 __可選項(xiàng)__。
function someFn (arg1: number, arg2?: string): void {} someFn(1);
當(dāng)該參數(shù)在不傳的時(shí)候有 缺省值 時(shí),可以使用 = 來為其賦予 __缺省值__。
function someFn (arg1: number, arg2: number = 1): number { return arg1 + arg2; } someFn(1); // 2
可選項(xiàng)與 缺省值 可以混搭。
function someFn (arg1: number, arg2: string = "str", arg3?: string): void {} someFn(1);
但 可選項(xiàng) 參數(shù)后不可跟任何 非可選項(xiàng) 參數(shù)。(以下代碼當(dāng)場爆炸)
function someFn (arg1: number, arg2?: string, arg3: string = "str"): void {} someFn(1);
可選項(xiàng)與 缺省值 不可同時(shí)使用在同一個(gè)值上。(以下代碼當(dāng)場爆炸)
function someFn (arg1: number, arg2?: string = "str"): void {} someFn(1);
可選項(xiàng) 也可用在接口的聲明中(__缺省值__ 不行,因?yàn)榻涌谑且环N類型的聲明,并非具體實(shí)例的實(shí)現(xiàn))。
泛型 泛型函數(shù) 基礎(chǔ)類型function someFn同時(shí)使用多個(gè)泛型(arg:T): T { return arg; } const str1: string = someFn ("str1"); const str2: string = someFn("str2");
function someFn箭頭函數(shù) & 泛型類型(arg1: T, arg2: U): T | U { return arg1; } const num1: string | number = someFn ("str1", 1); const str2: string | number = someFn("str2", 2);
const someFn:泛型接口(arg: T) => T = (arg: T): T => { return arg; }; const str: string = someFn("str");
interface InterfaceFn {(arg: T): T; } const someFn: InterfaceFn = (arg: T): T => { return arg; }; const str: string = someFn("str");
const someFn: {(arg: T): T; } = (arg: T): T => { return arg; }; const str: string = someFn("str");
interface InterfaceFn泛型類{ (arg: T): T; } const someFn: InterfaceFn = (arg: T): T => { return arg; }; const str: string = someFn("str");
原理與 接口泛型 一樣。
class SomeClass泛型約束{ someMethod (arg: T): T { return arg; } }
function someFn(arg: T): number { return arg.getTime(); } const date = new Date();
keyof、Record、Pick、Partial 太過復(fù)雜,真有需求還請(qǐng)自行查閱文檔。
.d.ts 文件在實(shí)際編碼過程中,我們經(jīng)常會(huì)定義很多自定義的 接口 與 __類__,如果我們?cè)诼暶髯兞康念愋蜁r(shí)需要用到它們,就算我們的代碼中并沒有調(diào)用到它們的實(shí)例,我們也必須手動(dòng)引入它們(最常見的例子是各種包裝類,他們并不會(huì)處理參數(shù)中傳入的變量,但他們會(huì)在接口上強(qiáng)規(guī)范參數(shù)的類型,并且會(huì)將該變量透傳給被包裝的類的對(duì)應(yīng)方法上)。
// foo.ts export default class FooClass { propA: number = 5; }
// bar.ts import FooClass from "./foo.ts"; export class BarClass { foo?: FooClass; }
這種使用方法在調(diào)用數(shù)量較少時(shí)尚且可以接受,但隨著業(yè)務(wù)的成長,被引用類型的數(shù)量和引用類型文件的數(shù)量同時(shí)上升,需要付出的精力便會(huì)隨其呈現(xiàn)出 o(n^2) 的增長趨勢。
這時(shí)我們可以選擇使用 .d.ts 文件,在你的業(yè)務(wù)目錄中創(chuàng)建 typings 文件夾,并在其內(nèi)新建屬于你的 xxx.d.ts 文件,并在其中對(duì)引用較多的類和接口進(jìn)行聲明(.d.ts 文件是用來進(jìn)行接口聲明的,不要在 .d.ts 文件里對(duì)聲明的結(jié)構(gòu)進(jìn)行實(shí)現(xiàn))。
注意:.d.ts 文件只是用于分析類型聲明及傳參校驗(yàn),如果需要進(jìn)行調(diào)用,還請(qǐng)直接 import 對(duì)應(yīng)模塊。
// my-types.d.ts declare class FooClass { propA: number; methodA (arg1: string): void; }
foo.ts 文件略
// bar.ts // 不需要再 import 了 export default class BarClass { foo?: FooClass; }
其他類型的聲明方式
// my-types.d.ts // 接口(沒有任何變化) interface InterfaceMy { propA: number; } // 函數(shù) function myFn (arg1: string): number; // 類型 type myType = number | string;使用注意
.d.ts 文件是類型聲明文件,不是具體業(yè)務(wù)模塊,不會(huì)產(chǎn)生具體的代碼實(shí)體,所以請(qǐng)?jiān)诼暶髂K時(shí)使用 declare 關(guān)鍵字,且不要使用 export 語句(如果使用了 export,該文件就會(huì)變成實(shí)體 ts 文件,不會(huì)被 ts 的自動(dòng)類型解析所識(shí)別,只能通過 import 使用)
枚舉(enum)一定不要定義在 .d.ts 里,這樣根本就引用不到(大概因?yàn)?typescript 的編譯過程是 文件 to 文件 的,所以本身作為數(shù)據(jù)類型輔助文件的 .d.ts 文件不會(huì)有翻譯實(shí)體的產(chǎn)出,自然也就無法在其內(nèi)定義一個(gè)右值字段(枚舉的每個(gè)值是可以作為右值使用的),那么其他引用這個(gè)字段的地方自然也就無法引用到這個(gè)值,繼而報(bào)錯(cuò)了)
0x02 反思本來想寫一寫常見的 TS 編譯錯(cuò)誤及造成這些錯(cuò)誤的原因來著,后來想了想,編譯出錯(cuò)了都不會(huì)查,還寫什么 TS 啊,
0xFF 失智以下幾點(diǎn)是我在使用 typescript 類型系統(tǒng)過程中遇到的一些智障問題與未解的疑問,歡迎大家一起討論。
為 window 變量增添屬性的各種姿勢錯(cuò)誤的為 window 增添屬性的姿勢:
window.someProperty = 1;
會(huì)觸發(fā) TS2339: Property "xxx" does not exist on type "Window" 錯(cuò)誤。
類型轉(zhuǎn)換法(window as any).someProperty = 1; (接口擴(kuò)展法window).someProperty = 1;
利用接口可以多處聲明,由編譯器進(jìn)行合并的特性進(jìn)行 hack。
interface Window { someProperty: number; } window.someProperty = 1;為什么對(duì)象類型最后不能跟尾逗號(hào)
下面的代碼當(dāng)場爆炸(因?yàn)?c: number, 最后的這個(gè)逗號(hào))。
const someObject: { a: number, b: number, c: number, } = { a: 1, b: 2, c: 3, };函數(shù)重載
當(dāng)一個(gè)函數(shù)在入?yún)⒉煌瑫r(shí)有較大的行為差距時(shí),可以使用函數(shù)重載梳理代碼結(jié)構(gòu)。
注意:參數(shù)中有回調(diào)函數(shù)時(shí),回調(diào)函數(shù)的參數(shù)數(shù)量變化并不應(yīng)該導(dǎo)致外層函數(shù)使用重載,只應(yīng)當(dāng)在當(dāng)前聲明函數(shù)的參數(shù)數(shù)量有變時(shí)才使用重載。
當(dāng)同時(shí)聲明多個(gè)重載時(shí),較為準(zhǔn)確的重載應(yīng)該放在更前面。
使用說明重載的使用方法比較智障,需要先 聲明 這個(gè)函數(shù)的不同重載方式,然后緊接著再對(duì)這個(gè)函數(shù)進(jìn)行定義。
定義時(shí)的參數(shù)個(gè)數(shù)取不同重載方法中參數(shù)個(gè)數(shù)最少的數(shù)量,隨后在其后追加 ...args: any[](或者更為準(zhǔn)確的類型定義寫法),用于接收多余的參數(shù)。
定義的返回值為所有重載返回值的并集。
而后在函數(shù)體內(nèi)部實(shí)現(xiàn)時(shí),通過判斷參數(shù)類型,自行實(shí)現(xiàn)功能的分流。
問題神奇的是 typescript 并不會(huì)校驗(yàn)重載的實(shí)現(xiàn)是否會(huì)真的在調(diào)用某個(gè)重載時(shí)返回這個(gè)重載真正要求的類型的值,下方例子中即使無論觸發(fā)哪個(gè)重載,都會(huì)返回 number,也不會(huì)被 typescript 檢查出來。
猜想:多次聲明一次實(shí)現(xiàn)難道是受制于 javascript 既有的語言書寫格式?
函數(shù)重載 of 類成員方法class SomeClass { someMethod (arg1: number, arg2: string, arg3: boolean): boolean; someMethod (arg1: number, arg2: string): string; someMethod (arg1: { arg1: number, arg2: string, }): number; someMethod (x: any, ...args: any[]): string | number | boolean { if ("object" === typeof x) { return 1; } else if (1 === args.length) { return 1; } else { return 1; } } }函數(shù)重載 of 函數(shù)
function someFn (arg1: number, arg2: string, arg3: boolean): boolean; function someFn (arg1: number, arg2: string): string; function someFn (arg1: { arg1: number, arg2: string, }): number; function someFn (x: any, ...args: any[]): string | number | boolean { if ("object" === typeof x) { return 1; } else if (1 === args.length) { return 1; } else { return 1; } }對(duì)象 key 的類型定義(索引標(biāo)記)
可以使用 type、interface、class 對(duì)象 key,但是使用方法十分麻煩,而且語法還不太一樣(type 使用 in,interface 與 class 使用 :)。
注意:索引值只可以使用數(shù)字與字符串。
type 法 限定 key 的數(shù)據(jù)類型其實(shí)就是放開了限制,讓該類型的實(shí)例上可以添加各種各樣的屬性。
這里冒號(hào) : 形式的不允許使用問號(hào)(可選項(xiàng)),但 in 形式的允許使用問號(hào)(可選項(xiàng))。
但其實(shí)帶不帶結(jié)果都一樣,實(shí)例都可以為空。
type SomeType1 = { [key: string]: string; } type SomeType2 = { [key in string]?: string; } const instance1: SomeType1 = {}; const instance2: SomeType2 = {};限定 key 只可以使用特定值
這里其中的 key 就成了必選項(xiàng)了,問號(hào)(可選項(xiàng))也有效果了。
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType1 = { [key in audioTypes]: string; } type SomeType2 = { [key in audioTypes]?: string; } const instance5: SomeType1 = { "ogg": "ogg", "mp3": "mp3", "wma": "wma", }; const instance6: SomeType2 = {};interface 法 限定 key 的數(shù)據(jù)類型
不可以用問號(hào)。
interface SomeInterface { [key: string]: string; } const instance: SomeInterface = {};限定 key 只可以使用特定值
只能通過 extends 已定義的 type 來實(shí)現(xiàn)。
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType = { [key in audioTypes]: string; } interface SomeInterface extends SomeType {} const instance: SomeInterface = { ogg: "ogg", mp3: "mp3", wma: "wma", };class 中的使用 限定 key 的數(shù)據(jù)類型
同樣也不可以使用問號(hào)(可選值)。
class SomeClass { [key: string]: string; } const instance: SomeClass = new SomeClass();限定 key 只可以使用特定值
通過 implements 其他的 interface、type 實(shí)現(xiàn)(多重實(shí)現(xiàn)可以合并)。
請(qǐng)記得 interface 只是數(shù)據(jù)格式規(guī)范,implements 之后要記得在 class 里寫實(shí)現(xiàn)
type audioTypes = "ogg" | "mp3" | "wma"; type SomeType = { [key in audioTypes]: string; } interface SomeInterface { [key: string]: string; } class ClassExtended implements SomeInterface, SomeType { ogg = "ogg"; mp3 = "mp3"; wma = "wma"; [key: string]: string; } const instance = new ClassExtended();如何初始化函數(shù)類變量?
初始化函數(shù)類變量時(shí),是否需要既給左值聲明類型,也給右值聲明類型?
這樣的語句應(yīng)如何斷句換行 & 換行后如何縮進(jìn)?
const someFn: (input: number, target: object) => SomeClass = (input: number, target: object): SomeClass => { // ... do sth };類型聲明 & npm 包版本
我們?cè)谄綍r(shí)使用一些類庫時(shí),某一生態(tài)環(huán)境下的多個(gè)包,可能會(huì)依賴同一個(gè)基礎(chǔ)包。同一個(gè)生態(tài)環(huán)境下的包,更新節(jié)奏或快或慢,此時(shí)便可能會(huì)存在基礎(chǔ)包版本不同的問題,npm 的解決方案是多版本共存,每個(gè)包引用自己對(duì)應(yīng)版本的基礎(chǔ)包。因?yàn)?typescript 的類型是基于文件進(jìn)行定義的,內(nèi)部結(jié)構(gòu)完全相同的兩個(gè)同名類型,在不同的文件中聲明便成了不同的類型。
此處以 @forawesome 項(xiàng)目組下的 fontawesome 庫進(jìn)行舉例,具體示例如下:
當(dāng)我們?cè)?vue 中使用 fortawesome 時(shí),需要把圖標(biāo)文件從對(duì)應(yīng)的包中導(dǎo)出(如免費(fèi)基礎(chǔ)包:@fortawesome/free-solid-svg-icons、免費(fèi)公司 logo 包:@fortawesome/free-brands-svg-icons),并使用 @fortawesome/fontawesome-svg-core 模塊的 library 方法導(dǎo)入到 vue 的運(yùn)行環(huán)境中。
import { faVolumeUp, faPlay, faPause, } from "@fortawesome/free-solid-svg-icons"; import { faWeibo, faWeixin, } from "@fortawesome/free-brands-svg-icons"; library.add( faVolumeUp, faPlay, faPause, faWeibo, faWeixin );
但我再剛開始開發(fā)時(shí)只使用了基礎(chǔ)包,公司 logo 包是我在開發(fā)途中用到時(shí)才引入的,但這時(shí) fortawesome 官方對(duì)整個(gè)庫進(jìn)行了版本升級(jí),具體功能并沒有什么改變,只是 fix 了一些 bug,版本號(hào)也只升級(jí)了一個(gè)小版本。
但在編譯時(shí) library.add 這里報(bào)告了錯(cuò)誤:
TS2345: Argument of type "IconDefinition" is not assignable to parameter of type "IconDefinitionOrPack". Type "IconDefinition" is not assignable to type "IconPack".`
經(jīng)過跟進(jìn)發(fā)現(xiàn):
@forawesome/fontawesome-svg-core 的 library.add 的參數(shù)所要求的 IconDefinition 類型來自頂層 node_modules 安裝的公用的 @fortawesome/fontawesome-common-types 包的 index.d.ts 文件。
而 @fortawesome/free-brands-svg-icons 中字體的類型 IconDefinition 來自 @fortawesome/free-brands-svg-icons 自身內(nèi)部 node_modules 里安裝的高版本的 @fortawesome/fontawesome-common-types 的 index.d.ts 文件。
雖然兩個(gè)類型的定義一模一樣,但因?yàn)椴皇峭粋€(gè)文件定義的,所以是完全不同的兩種類型,因而造成了類型不匹配,無法正常編譯。
遇到這種問題時(shí),升級(jí)對(duì)應(yīng)包的版本就可以了。
復(fù)雜泛型嵌套的生成方法與可讀性talk is cheap, show you the dunce.
節(jié)選自 vue/types/vue.d.ts,我已經(jīng)看暈了,調(diào)用方想要查錯(cuò)的時(shí)候到底怎么看呢。
export interface VueConstructor泛型(嵌套) + 合并聲明 + 混入{ new (options?: ThisTypedComponentOptionsWithArrayProps ): CombinedVueInstance >; // ideally, the return type should just contains Props, not Record . But TS requires Base constructors must all have the same return type. new (options?: ThisTypedComponentOptionsWithRecordProps ): CombinedVueInstance >; new (options?: ComponentOptions ): CombinedVueInstance >; extend(options?: ThisTypedComponentOptionsWithArrayProps ): ExtendedVue >; extend(options?: ThisTypedComponentOptionsWithRecordProps ): ExtendedVue ; extend (definition: FunctionalComponentOptions , PropNames[]>): ExtendedVue >; extend (definition: FunctionalComponentOptions >): ExtendedVue ; extend(options?: ComponentOptions ): ExtendedVue ; nextTick(callback: () => void, context?: any[]): void; nextTick(): Promise set (object: object, key: string, value: T): T; set (array: T[], key: number, value: T): T; delete(object: object, key: string): void; delete (array: T[], key: number): void; directive( id: string, definition?: DirectiveOptions | DirectiveFunction ): DirectiveOptions; filter(id: string, definition?: Function): Function; component(id: string): VueConstructor; component (id: string, constructor: VC): VC; component(id: string, definition: AsyncComponent): ExtendedVue ; component(id: string, definition?: ThisTypedComponentOptionsWithArrayProps ): ExtendedVue >; component(id: string, definition?: ThisTypedComponentOptionsWithRecordProps ): ExtendedVue ; component (id: string, definition: FunctionalComponentOptions , PropNames[]>): ExtendedVue >; component (id: string, definition: FunctionalComponentOptions >): ExtendedVue ; component(id: string, definition?: ComponentOptions ): ExtendedVue ; use (plugin: PluginObject | PluginFunction , options?: T): void; use(plugin: PluginObject | PluginFunction , ...options: any[]): void; mixin(mixin: VueConstructor | ComponentOptions ): void; compile(template: string): { render(createElement: typeof Vue.prototype.$createElement): VNode; staticRenderFns: (() => VNode)[]; }; config: VueConfiguration; }
0 === san;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99185.html
摘要:解決問題當(dāng)我們?cè)谟邢迣挾鹊母讣?jí)內(nèi)部時(shí),如何創(chuàng)建一個(gè)全瀏覽器寬度的容器例子文字區(qū)域?qū)挾裙潭ň又袌D片全屏展示知道你們懶可直接復(fù)制看效果有限寬度的父容器無用文字幾分電視劇方了解到失聯(lián)飛機(jī)萊德斯基發(fā)了端上了電視劇方了解到失聯(lián)飛機(jī)淡藍(lán)色積分的 1. 解決問題 當(dāng)我們?cè)谟邢迣挾鹊母讣?jí)內(nèi)部時(shí),如何創(chuàng)建一個(gè)全瀏覽器寬度的容器? 2. 例子 2.1 文字區(qū)域 寬度固定 居中, 圖片 全屏展示 知道你們...
摘要:怎么影響了我的思考方式對(duì)前端開發(fā)者來說,能強(qiáng)化了面向接口編程這一理念。使用的過程就是在加深理解的過程,確實(shí)面向接口編程天然和靜態(tài)類型更為親密。摘要: 學(xué)會(huì)TS思考方式。 原文:TypeScript - 一種思維方式 作者:zhangwang Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 電影《降臨》中有一個(gè)觀點(diǎn),語言會(huì)影響人的思維方式,對(duì)于前端工程師來說,使用 typescript 開...
摘要:怎么影響了我的思考方式對(duì)前端開發(fā)者來說,能強(qiáng)化了面向接口編程這一理念。使用的過程就是在加深理解的過程,確實(shí)面向接口編程天然和靜態(tài)類型更為親密。 電影《降臨》中有一個(gè)觀點(diǎn),語言會(huì)影響人的思維方式,對(duì)于前端工程師來說,使用 typescript 開發(fā)無疑就是在嘗試換一種思維方式做事情。 其實(shí)直到最近,我才開始系統(tǒng)的學(xué)習(xí) typescript ,前后大概花了一個(gè)月左右的時(shí)間。在這之前,我也在...
摘要:特此寫個(gè)流水賬總結(jié),供自己以后羞恥的回顧。正逢月計(jì)劃辭職回家玩游戲過個(gè)暑假,結(jié)果在如今部門老大的忽悠下加入到了新東家。和組長兩人繼續(xù)沒晝夜的忙活,最終也按時(shí)交差,上了線。卷土重來,回報(bào)過去的一份念舊,期待的美好,個(gè)人選型入坑。 前言 2017年發(fā)生了太多的事情,結(jié)了婚,住進(jìn)了新家,成功的播了種,當(dāng)上了準(zhǔn)爸爸。公司也蒸蒸日上搬進(jìn)了高大上的寫字樓。前端的坑越來越大,都來不及填。特此寫個(gè)流水...
閱讀 1525·2021-08-09 13:47
閱讀 2783·2019-08-30 15:55
閱讀 3509·2019-08-29 15:42
閱讀 1128·2019-08-29 13:45
閱讀 3022·2019-08-29 12:33
閱讀 1755·2019-08-26 11:58
閱讀 997·2019-08-26 10:19
閱讀 2425·2019-08-23 18:00