在這篇文章中,分享TypeScript中的5個(gè)不良實(shí)踐以及如何避免它們。
1. 將錯(cuò)誤聲明為Any類型
示例
在以下代碼片段中,我們捕獲錯(cuò)誤然后將其聲明為any類型。
async function asyncFunction() {
try {
const response = await doSomething();
return response;
} catch (err: any) {
toast(`Failed to do something: ${err.message}`);
}
}
為什么這是不好的 ?
沒有保證錯(cuò)誤會(huì)有一個(gè)類型為字符串的message字段。
不幸的是,由于類型斷言,代碼讓我們假設(shè)它確實(shí)有。
代碼在開發(fā)環(huán)境中可以針對(duì)特定測試用例工作,但在生產(chǎn)環(huán)境中可能會(huì)嚴(yán)重失敗。
應(yīng)該做什么替代方案 ?
不要設(shè)置錯(cuò)誤類型。它應(yīng)該默認(rèn)為unknown
。
你可以做到以下幾點(diǎn):
選項(xiàng)1: 使用類型守衛(wèi)檢查錯(cuò)誤是否為正確的類型。
async functionasyncFunction() {
try {
const response = awaitdoSomething();
return response;
} catch (err) {
const toastMessage = hasMessage(err)
? `Failed to do something: ${err.message}`
: `Failed to do something`;
toast(toastMessage);
}
}
// 我們使用類型守衛(wèi)首先進(jìn)行檢查
functionhasMessage(value: unknown): value is { message: string } {
return (
value != null &&
typeof value === "object" &&
"message"in value &&
typeof value.message === "string"
);
}
// 你也可以簡單地檢查錯(cuò)誤是否是Error的實(shí)例
const toastMessage = err instanceofError
? `Failed to do something: ${err.message}`
: `Failed to do something`;
選項(xiàng)2(推薦): 不要對(duì)錯(cuò)誤類型做出假設(shè)
與其對(duì)錯(cuò)誤類型做出假設(shè),不如明確處理每種類型并為用戶提供適當(dāng)?shù)姆答仭?/span>
如果你無法確定具體的錯(cuò)誤類型,最好顯示完整的錯(cuò)誤信息而不是部分細(xì)節(jié)。
有關(guān)錯(cuò)誤處理的更多信息,請(qǐng)查看這篇出色的指南:編寫更好的錯(cuò)誤消息。
2. 函數(shù)中有多個(gè)連續(xù)的相同類型參數(shù)
示例
export function greet(
firstName: string,
lastName: string,
city: string,
email: string
) {
// 做一些事情...
}
為什么這是不好的 ?
- 你可能不小心以錯(cuò)誤的順序傳遞參數(shù):
// 我們顛倒了firstName和lastName,但TypeScript不會(huì)捕獲這一點(diǎn)
greet("Curry", "Stephen", "LA", "stephen.curry@gmail.com");
- 在代碼審查中,尤其是在看到函數(shù)調(diào)用之前,更難以理解每個(gè)參數(shù)代表什么。
應(yīng)該做什么替代方案 ?
使用對(duì)象參數(shù)來明確每個(gè)字段的目的,并最小化錯(cuò)誤的風(fēng)險(xiǎn)。
export function greet(params: {
firstName: string;
lastName: string;
city: string;
email: string;
}) {
// 做一些事情...
}
3. 函數(shù)有多個(gè)分支且沒有返回類型
示例
function getAnimalDetails(animalType: "dog" | "cat" | "cow") {
switch (animalType) {
case"dog":
return { name: "Dog", sound: "Woof" };
case"cat":
return { name: "Cat", sound: "Meow" };
case"cow":
return { name: "Cow", sound: "Moo" };
default:
// 這確保TypeScript捕獲未處理的案例
((_: never) => {})(animalType);
}
}
為什么這是不好的 ?
- 添加新的
animalType
可能導(dǎo)致返回結(jié)構(gòu)不正確的對(duì)象。 - 返回類型結(jié)構(gòu)的更改可能會(huì)導(dǎo)致代碼的其他部分出現(xiàn)難以追蹤的問題。
- 拼寫錯(cuò)誤可能導(dǎo)致推斷出錯(cuò)誤的類型。
應(yīng)該做什么替代方案 ?
明確指定函數(shù)的返回類型:
type Animal = {
name: string;
sound: string;
};
functiongetAnimalDetails(animalType: "dog" | "cat" | "cow"): Animal {
switch (animalType) {
case"dog":
return { name: "Dog", sound: "Woof" };
case"cat":
return { name: "Cat", sound: "Meow" };
case"cow":
return { name: "Cow", sound: "Moo" };
default:
// 這確保TypeScript捕獲未處理的案例
((_: never) => {})(animalType);
}
}
4. 添加不必要的類型而不是使用可選字段
示例
type Person = {
name: string;
age: number;
};
typePersonWithAddress = Person & {
address: string;
};
typePersonWithAddressAndEmail = PersonWithAddress & {
email: string;
};
typePersonWithEmail = Person & {
email: string;
};
為什么這是不好的 ?
- 不可擴(kuò)展:添加新字段需要?jiǎng)?chuàng)建多個(gè)新類型。
- 使得類型檢查更加復(fù)雜,需要額外的類型守衛(wèi)。
- 導(dǎo)致令人困惑的類型名稱和更難的維護(hù)。
應(yīng)該做什么替代方案 ?
使用可選字段來保持你的類型簡單和可維護(hù):
type Person = {
name: string;
age: number;
address?: string;
email?: string;
};
5. 在不同組件級(jí)別使屬性變?yōu)榭蛇x
示例
interface TravelFormProps {
disabled?: boolean;
}
exportfunctionTravelForm(props: TravelFormProps) {
// 使用日期范圍選擇器組件...
}
interfaceDateRangePickerProps {
disabled?: boolean;
}
functionDateRangePicker(props: DateRangePickerProps) {
// 使用日期選擇器組件...
}
interfaceDatePickerProps {
disabled?: boolean;
}
functionDatePicker(props: DatePickerProps) {}
為什么這是不好的 ?
- 容易忘記傳遞
disabled
屬性,導(dǎo)致部分啟用的表單。
應(yīng)該做什么替代方案 ?
使共享字段在內(nèi)部組件中必需。
這將確保正確的屬性傳遞。這對(duì)于低級(jí)別的組件尤其重要,以便盡早捕獲任何疏忽。
在上面的例子中,disabled
現(xiàn)在在所有內(nèi)部組件中都是必需的。
interface TravelFormProps {
disabled?: boolean;
}
exportfunctionTravelForm(props: TravelFormProps) {
// 使用日期范圍選擇器組件...
}
interfaceDateRangePickerProps {
disabled: boolean | undefined;
}
functionDateRangePicker(props: DateRangePickerProps) {
// 使用日期選擇器組件...
}
interfaceDatePickerProps {
disabled: boolean | undefined;
}
functionDatePicker(props: DatePickerProps) {}
注意:如果你正在為庫設(shè)計(jì)組件,我不推薦這樣做,因?yàn)楸匦枳侄涡枰嗟墓ぷ鳌?/span>
總結(jié)
TypeScript是令人驚嘆的,但沒有工具???是完美的。
避免這5個(gè)錯(cuò)誤將幫助你編寫更干凈、更安全、更易于維護(hù)的代碼。
閱讀原文:原文鏈接
該文章在 2025/1/10 11:09:59 編輯過