注:本文主要內(nèi)容來自于官方文檔的理解
當(dāng)我們需要為第三方不支持ts的庫編寫類型聲明文件時桨醋,本文包含一些需要避免的不太建議的用法姐呐,本文主要內(nèi)容來源在此處: Do's and Don'ts
不要使用 Number
String
Boolean
Symbol
Object
等類型崭庸,而是使用 number
string
boolean
symbol
object
等類型属划,因?yàn)榇髮戦_頭的都是js中的自執(zhí)行的基本包裝類型涧至,而非原始類型诅蝶,比如 var a = 'ddd'
中自執(zhí)行的 a = new String('ddd');
退个,很怪不募壕,
在使用泛型時,泛型參數(shù)一定要被使用
interface Something<T> {
name: string;
}
上述泛型接口例子语盈,泛型T沒被使用舱馅,這會導(dǎo)致當(dāng)我們傳入不同類型時,產(chǎn)生的變量可以被互相賦值刀荒,貼出官方FAQ例子
interface Something<T> {
name: string;
}
let x: Something<number>;
let y: Something<string>;
x = y;
x 和 y可以被互相賦值代嗤,這很怪異,泛型根本沒有作用缠借,正確的使用泛型應(yīng)該是這個姿勢才對
interface Something<T> {
name: T;
}
否則干毅,就別強(qiáng)行使用泛型了。泼返。硝逢。
當(dāng)函數(shù)沒有返回值時,使用void 而不是 any
function test(): any{
}
const a = test();
a.run();
ts 不會報(bào)錯绅喉,但是本身趴捅,test函數(shù)沒有返回值,自然a.run() 應(yīng)該報(bào)錯才對霹疫,所以,不要偷懶把該寫void的地方寫成any W劢妗丽蝎!
回調(diào)函數(shù)中,無需使用可選參數(shù) 因?yàn)楹瘮?shù)參數(shù)在被賦值時膀藐,被賦值的函數(shù)參數(shù)數(shù)量本身是可以缺少的
function test(callback: (num: number) => void) {
callback(5);
}
test((num: string) => { // 報(bào)錯
console.log("What");
});
test(() => { // 通過
console.log("What");
});
本例我們的test函數(shù)在聲明需要的callback參數(shù)時屠阻,聲明了callback 有一個number類型參數(shù),ts中進(jìn)行函數(shù)兼容性判斷時额各,函數(shù)參數(shù)是雙向協(xié)變的(通過嚴(yán)格模式可以設(shè)置成逆變)国觉,返回值是協(xié)變的(ps:為什么這么設(shè)計(jì)呢,大概是因?yàn)槲覀兤綍rjs中使用map reduce filter時也并沒有三個參數(shù)全用上虾啦。因?yàn)閺?qiáng)行寫上簡直是無用功麻诀。。)傲醉,
所以蝇闭,在回調(diào)函數(shù)中使用可選參數(shù)是多余的,因?yàn)榧硬患佑脖希际强蛇x的呻引。另外可選參數(shù)的意義是會根據(jù)參數(shù)數(shù)量的不同而產(chǎn)生不同的調(diào)用,用在這里也不合適
interface Fetcher {
getObject(done: (data: any, elapsedTime?: number) => void): void;
}
interface Fetcher {
getObject(done: (data: any, elapsedTime: number) => void): void;
}
兩者等價吐咳。
和上面同理逻悠,編寫僅在回調(diào)函數(shù)參數(shù)數(shù)量上面不同的函數(shù)重載是沒有意義的
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
// 無需寫重載
declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
上面兩行和下面一行等價元践!
函數(shù)重載過程中,要按照參數(shù)復(fù)雜度從小到大排序童谒,因?yàn)閠ypescript在匹配函數(shù)類型時是按照聲明順序匹配的
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: any): any;
按照一個包含另一個的從小到大順序排列
當(dāng)函數(shù)重載的返回值類型相同時单旁,使用可選參數(shù)而不是函數(shù)重載,
// 錯誤
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
// 正確
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
為什么呢惠啄,當(dāng)返回值類型相同時使用函數(shù)重載會導(dǎo)致兩個問題慎恒,
- 賦值給回調(diào)函數(shù)時因?yàn)槟硞€重載滿足條件而錯誤賦值
function fn(callback: (a: string, b: number, c: number) => void) { }
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
var x: Example;
fn(x.diff);
我們定義了fn函數(shù),接受的回調(diào)函數(shù)有一個string 兩個number類型的參數(shù)撵渡,當(dāng)我們對diff函數(shù)使用重載時融柬,我們可以將diff函數(shù)賦值給callback回調(diào)函數(shù),因?yàn)榈谝粋€重載滿足一個string參數(shù)趋距,這顯然使我們不想見到的粒氧,因?yàn)榈诙€重載第三個重載都不滿足callback函數(shù),是用可選參數(shù)可以避免此問題
function fn(callback: (a: string, b: number, c: number) => void) { }
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
var x: Example;
fn(x.diff);
ts報(bào)錯节腐,這樣才是我們想要的
2.當(dāng)我們顯式傳入undefined時外盯,函數(shù)重載會導(dǎo)致報(bào)錯,
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
var x: Example;
x.diff("something", true ? undefined : "hour")
當(dāng)時用重載時翼雀,ts會報(bào)錯undefined不能賦值給string饱苟,
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
var x: Example;
x.diff("something", true ? undefined : "hour")
使用用可選參數(shù)可以避免此問題,因?yàn)槲覀兾磦鲄?shù)時默認(rèn)的值就是undefined狼渊,因此箱熬,顯式傳入undefined應(yīng)該與未傳表現(xiàn)一致才對,這才符合js的運(yùn)行過程狈邑,可選參數(shù)可以解決這個問題城须。
當(dāng)函數(shù)重載時,只有參數(shù)類型不一樣時米苹,使用聯(lián)合類型
// 錯誤
interface Moment {
utcOffset(b: number): Moment;
utcOffset(b: string): Moment;
}
// 正確
interface Moment {
utcOffset(b: number|string): Moment;
}
因?yàn)槭褂寐?lián)合類型可以既接收單一類型的值糕伐,也可以接收聯(lián)合類型的值,函數(shù)重載只能接收單一類型的值
function fn(x: number|string) {
return moment().utcOffset(x);
}
函數(shù)重載時傳入聯(lián)合類型x報(bào)錯蘸嘶,是用聯(lián)合類型時可以傳入聯(lián)合類型良瞧,
最后希望大家為優(yōu)秀的第三方庫多做貢獻(xiàn),一起豐富typescript生態(tài)训唱!