TypeScript 是一種出色的工具,可以讓我們的生活更輕鬆並避免 bug,但有時使用起來感覺不知所措。

本文概述了專業人士使用的 7 個 TypeScript 技巧,它們將使您的生活更輕鬆。

原文出處:https://dev.to/ruppysuppy/7-secret-typescript-tricks-pros-use-3ckg

1. 型別推理

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 是否存在。

2. 字串類型

通常你需要一個變數的特定值,這就是文字類型派上用場的地方。

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];

3.類型守衛

類型保護 是另一種縮小變數類型的方法:

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 是如何工作的一個簡化。

4.索引簽名

當對像中有動態鍵時,可以使用索引簽名來定義其類型:

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,
  // ...
};

5.泛型

泛型 是一個強大的工具,可以讓您的程式碼更易於重用。它允許您定義一個類型,該類型將由您的函數的使用決定

在以下示例中,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);

6. 不可變類型

您可以通過加入 as const 使您的類型不可變。這確保您不會意外更改值。

const ErrorMessages = {
  InvalidEmail: "Invalid email",
  InvalidPassword: "Invalid password",
  // ...
} as const;

// This will throw an error
ErrorMessages.InvalidEmail = "New error message";

7. 部分、選擇、省略和必需類型

通常在使用 serverlocal data 時,您需要將一些屬性設置為 optionalrequired

而不是使用相同資料的略微更改版本定義數百個接口。您可以使用 PartialPickOmitRequired 類型來做到這一點。

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;

其中 BC 是任何類型。


謝謝閱讀,希望對您有幫助!


共有 0 則留言