TypeScript 是一種出色的工具,可以讓我們的生活更輕鬆並避免 bug,但有時使用起來感覺不知所措。
本文概述了專業人士使用的 7 個 TypeScript 技巧,它們將使您的生活更輕鬆。
原文出處:https://dev.to/ruppysuppy/7-secret-typescript-tricks-pros-use-3ckg
Typescript 足夠聰明,可以在您幫助縮小資料類型時推斷資料類型。
enum CounterActionType {
Increment = "INCREMENT",
IncrementBy = "INCREMENT_BY",
}
interface IncrementAction {
type: CounterActionType.Increment;
}
interface IncrementByAction {
type: CounterActionType.IncrementBy;
payload: number;
}
type CounterAction =
| IncrementAction
| IncrementByAction;
function reducer(state: number, action: CounterAction) {
switch (action.type) {
case CounterActionType.Increment:
// TS infers that the action is IncrementAction
// & has no payload
return state + 1;
case CounterActionType.IncrementBy:
// TS infers that the action is IncrementByAction
// & has a number as a payload
return state + action.payload;
default:
return state;
}
}
如上所示,TypeScript 根據 type
屬性推斷操作的類型,因此您無需檢查 payload
是否存在。
通常你需要一個變數的特定值,這就是文字類型派上用場的地方。
type Status = "idle" | "loading" | "success" | "error";
它也適用於數字:
type Review = 1 | 2 | 3 | 4 | 5;
// or better yet:
const reviewMap = {
terrible: 1,
average: 2,
good: 3,
great: 4,
incredible: 5,
} as const;
// This will generate the same type as above,
// but it's much more maintainable
type Review = typeof reviewMap[keyof typeof reviewMap];
類型保護 是另一種縮小變數類型的方法:
function isNumber(value: any): value is number {
return typeof value === "number";
}
const validateAge = (age: any) => {
if (isNumber(age)) {
// validation logic
// ...
} else {
console.error("The age must be a number");
}
};
注意:在上面的示例中,最好使用:
const validateAge = (age: number) => {
// ...
};
這個例子是為了展示 type guards 是如何工作的一個簡化。
當對像中有動態鍵時,可以使用索引簽名來定義其類型:
enum PaticipationStatus {
Joined = "JOINED",
Left = "LEFT",
Pending = "PENDING",
}
interface ParticipantData {
[id: string]: PaticipationStatus;
}
const participants: ParticipantData = {
id1: PaticipationStatus.Joined,
id2: PaticipationStatus.Left,
id3: PaticipationStatus.Pending,
// ...
};
泛型 是一個強大的工具,可以讓您的程式碼更易於重用。它允許您定義一個類型,該類型將由您的函數的使用決定。
在以下示例中,T
是通用類型:
const clone = <T>(object: T) => {
const clonedObject: T = JSON.parse(JSON.stringify(object));
return clonedObject;
};
const obj = {
a: 1,
b: {
c: 3,
},
};
const obj2 = clone(obj);
您可以通過加入 as const
使您的類型不可變。這確保您不會意外更改值。
const ErrorMessages = {
InvalidEmail: "Invalid email",
InvalidPassword: "Invalid password",
// ...
} as const;
// This will throw an error
ErrorMessages.InvalidEmail = "New error message";
通常在使用 server 和 local data 時,您需要將一些屬性設置為 optional 或 required。
而不是使用相同資料的略微更改版本定義數百個接口。您可以使用 Partial
、Pick
、Omit
和 Required
類型來做到這一點。
interface User {
name: string;
age?: number;
email: string;
}
type PartialUser = Partial<User>;
type PickUser = Pick<User, "name" | "age">;
type OmitUser = Omit<User, "age">;
type RequiredUser = Required<User>;
// PartialUser is equivalent to:
// interface PartialUser {
// name?: string;
// age?: number;
// email?: string;
// }
// PickUser is equivalent to:
// interface PickUser {
// name: string;
// age?: number;
// }
// OmitUser is equivalent to:
// interface OmitUser {
// name: string;
// email: string;
// }
// RequiredUser is equivalent to:
// interface RequiredUser {
// name: string;
// age: number;
// email: string;
// }
當然,你可以使用 intersection 來組合它們:
type A = B & C;
其中 B
和 C
是任何類型。
謝謝閱讀,希望對您有幫助!