鏈接:https://medium.com/@technicadil_001/how-to-write-better-types...
作者:Debabrata Dash
原標題:How to write better Typescript codes?
在本文中,我們將討論大約 15 個編寫更好的 Typescript 代碼的技巧。
譯者:本文討論了 15 個實用技巧,以幫助開發者編寫更好的 TypeScript 代碼。這些技巧包括可選鏈接、映射類型、實用類型等,旨在提高代碼的安全性、可讀性和功能性。通過這些技巧,開發者可以更有效地管理數據類型,從而構建更穩健的應用程序。
1 可選鏈 (?.):
通過可選的鏈接,您可以安全地訪問嵌套的屬性或方法,而無需擔心 null 值或未定義的值。如果任何中間屬性為 null 或未定義,它就會短路評估。
const user = {
name: 'Piotr',
address: {
city: 'Warsaw',
postalCode: '00-240'
}
};
const postalCode = user.address?.postalCode;
console.log(postalCode); // 00-240
const invalidCode = user.address?.postalCode?.toLowerCase();
console.log(invalidCode); // Output: undefined
2 使用映射類型進行轉換
映射類型允許您通過轉換現有類型的屬性來創建新類型。
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
3 善用實用程序類型
TypeScript 提供了多種實用程序類型來幫助進行常見的類型轉換。
i)Partial<T>:使所有屬性成為可選屬性。
ii) Required<T>: 使所有屬性成為必需屬性。
iii) Readonly<T>: 將所有屬性設置為只讀。
iv) Record<K, T>: 使用類型為 T 的鍵 K 創建一個類型。
type Person = {
name: string;
age: number;
};
type PartialPerson = Partial<Person>;
type ReadonlyPerson = Readonly<Person>;
4 類型防護
使用 Type Guards 縮小條件塊中的類型範圍
function isString(value: unknown): value is string {
return typeof value === 'string';
}
5 模板文字類型
Tese 允許您通過組合字符串文字來創建新的字符串類型。
type EventName = 'click' | 'hover';
type EventHandlerName = `${EventName}Handler`; // 'clickHandler' | 'hoverHandler'
6 使用索引訪問類型
使用索引訪問類型來提取屬性的類型。
type Person = { name: string; age: number };
type NameType = Person['name']; // string
7 將映射類型中的鍵重新映射
創建新類型時,轉換鍵。
type PrefixKeys<T, P extends string> = {
[K in keyof T as `${P}${K & string}`]: T[K]
};
type PrefixedPerson = PrefixKeys<{ name: string; age: number }, 'prefix_'>;
// { prefix_name: string; prefix_age: number }
8 Discriminated 聯合類型
這些可以幫助您創建不同類型的類型安全聯合。
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number };
function getArea(shape: Shape) {
switch (shape.kind) {
case 'circle': return Math.PI * shape.radius ** 2;
case 'square': return shape.side ** 2;
}
}
9 泛型中的類型推斷
利用 ‘infer’ 提取並使用條件類型中的類型。
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type Fn = () => number;
type Result = ReturnType<Fn>; // number
10 模塊增強
使用新功能擴展現有模塊。
// augmentations.ts
import 'express';
declare module 'express' {
interface Request {
user?: { id: string; role: string };
}
}
11 聲明合併的interface
合併 interface 以擴展類型,對於第三方庫尤其有用。
interface Window {
myCustomProperty: string;
}
window.myCustomProperty = 'Hello!';
12 函數重載
提供多個函數簽名以更好地進行類型檢查。
function createDate(timestamp: number): Date;
function createDate(year: number, month: number, day: number): Date;
function createDate(x: number, y?: number, z?: number): Date {
return y !== undefined && z !== undefined ? new Date(x, y, z) : new Date(x);
}
13 Branded 類型
使用 Branded 類型來創建名義類型。
type UserId = string & { _brand: 'UserId' };
function createUserId(id: string): UserId {
return id as UserId;
}
14 具有條件類型的模板文字類型
將模板文字類型與條件類型相結合以進行高級字符串操作。
type ExtractRouteParams<T extends string> = T extends `/${infer Param}/${infer Rest}`
? { param: Param } & ExtractRouteParams<`/${Rest}`>
: {};
type Params = ExtractRouteParams<'/user/:id/posts/:postId'>;
// { param: 'user' } & { param: 'posts' }
15 可變參數元組類型
Typescript 4+ 支持可變元組類型,允許元組捕獲數組的其餘部分。
type Push<T extends any[], V> = [...T, V];
type Result = Push<[1, 2, 3], 4>; // [1, 2, 3, 4]