Number
,String
,Boolean
和Object
不要使用如下類型Number
,String
,Boolean
或Object
。 這些類型指的是非原始的裝盒對象,它們幾乎沒在JavaScript代碼里正確地使用過。
/* 錯誤 */
function reverse(s: String): String;
應(yīng)該使用類型number
,string
,and boolean
。
/* OK */
function reverse(s: string): string;
如果你就要使用Object
類型,考慮使用any
代替。 目前在TypeScript里無法指定一個對象“不是一個原始值”。
不要定義一個從來沒使用過其類型參數(shù)的泛型類型。 了解詳情 TypeScript FAQ page。
不要為返回值被忽略的回調(diào)函數(shù)設(shè)置一個any
類型的返回值類型:
/* 錯誤 */
function fn(x: () => any) {
x();
}
應(yīng)該給返回值被忽略的回調(diào)函數(shù)設(shè)置void
類型的返回值類型:
/* OK */
function fn(x: () => void) {
x();
}
為什么:使用void
相對安全,因?yàn)樗乐沽四悴恍⌒氖褂?code>x的返回值:
function fn(x: () => void) {
var k = x(); // oops! meant to do something else
k.doSomething(); // error, but would be OK if the return type had been 'any'
}
不要在回調(diào)函數(shù)里使用可選參數(shù)除非你真的要這么做:
/* 錯誤 */
interface Fetcher {
getObject(done: (data: any, elapsedTime?: number) => void): void;
}
這里有一種特殊的意義:done
回調(diào)函數(shù)可能以1個參數(shù)或2個參數(shù)調(diào)用。 代碼大概的意思是說這個回調(diào)函數(shù)不在乎是否有 elapsedTime
參數(shù), 但是不需要把這個參數(shù)當(dāng)成可選參數(shù)來達(dá)到此目的 -- 因?yàn)榭偸窃试S提供一個接收較少參數(shù)的回調(diào)函數(shù)。
應(yīng)該寫出回調(diào)函數(shù)的非可選參數(shù):
/* OK */
interface Fetcher {
getObject(done: (data: any, elapsedTime: number) => void): void;
}
不要因?yàn)榛卣{(diào)函數(shù)參數(shù)個數(shù)不同而寫不同的重載:
/* 錯誤 */
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
應(yīng)該只使用最大參數(shù)個數(shù)寫一個重載:
/* OK */
declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
為什么:回調(diào)函數(shù)總是可以忽略某個參數(shù)的,因此沒必要為參數(shù)少的情況寫重載。 參數(shù)少的回調(diào)函數(shù)首先允許錯誤類型的函數(shù)被傳入,因?yàn)樗鼈兤ヅ涞谝粋€重載。
不要把一般的重載放在精確的重載前面:
/* 錯誤 */
declare function fn(x: any): any;
declare function fn(x: HTMLElement): number;
declare function fn(x: HTMLDivElement): string;
var myElem: HTMLDivElement;
var x = fn(myElem); // x: any, wat?
應(yīng)該排序重載令精確的排在一般的之前:
/* OK */
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: any): any;
var myElem: HTMLDivElement;
var x = fn(myElem); // x: string, :)
為什么:TypeScript會選擇第一個匹配到的重載當(dāng)解析函數(shù)調(diào)用的時候。 當(dāng)前面的重載比后面的“普通”,那么后面的被隱藏了不會被調(diào)用。
不要為僅在末尾參數(shù)不同時寫不同的重載:
/* 錯誤 */
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
應(yīng)該盡可能使用可選參數(shù):
/* OK */
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
注意這在所有重載都有相同類型的返回值時會不好用。
為什么:有兩種生要的原因。
TypeScript解析簽名兼容性時會查看是否某個目標(biāo)簽名能夠使用源的參數(shù)調(diào)用, 且允許外來參數(shù)。 下面的代碼暴露出一個bug,當(dāng)簽名被正確的使用可選參數(shù)書寫時:
function fn(x: (a: string, b: number, c: number) => void) { }
var x: Example;
// When written with overloads, OK -- used first overload
// When written with optionals, correctly an error
fn(x.diff);
第二個原因是當(dāng)使用了TypeScript“嚴(yán)格檢查null”特性時。 因?yàn)闆]有指定的參數(shù)在JavaScript里表示為undefined
,通常顯示地為可選參數(shù)傳入一個undefined
。 這段代碼在嚴(yán)格null模式下可以工作:
var x: Example;
// When written with overloads, incorrectly an error because of passing 'undefined' to 'string'
// When written with optionals, correctly OK
x.diff("something", true ? undefined : "hour");
不要為僅在某個位置上的參數(shù)類型不同的情況下定義重載:
/* WRONG */
interface Moment {
utcOffset(): number;
utcOffset(b: number): Moment;
utcOffset(b: string): Moment;
}
應(yīng)該盡可能使用聯(lián)合類型:
/* OK */
interface Moment {
utcOffset(): number;
utcOffset(b: number|string): Moment;
}
注意我們沒有讓b
成為可選的,因?yàn)楹灻姆祷刂殿愋筒煌?/p>
為什么:This is important for people who are "passing through" a value to your function:
function fn(x: string): void;
function fn(x: number): void;
function fn(x: number|string) {
// When written with separate overloads, incorrectly an error
// When written with union types, correctly OK
return moment().utcOffset(x);
}
更多建議: