欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

typescript常見高級技巧總結(jié)

 更新時間:2022年11月15日 11:01:26   作者:程序員山月  
這篇文章主要介紹了typescript常見高級技巧總結(jié),需要的朋友可以參考下

用了一段時間的 typescript 之后,深感中大型項目中 typescript 的必要性,它能夠提前在編譯期避免許多 bug,如很惡心的拼寫問題。而越來越多的 package 也開始使用 ts,學(xué)習(xí) ts 已是勢在必行。

以下是我在工作中總結(jié)到的比較實用的 typescript 技巧。

01 keyof

keyofObject.keys 略有相似,只不過 keyofinterface 的鍵。

interface Point {
    x: number;
    y: number;
}

// type keys = "x" | "y"
type keys = keyof Point;

假設(shè)有一個 object 如下所示,我們需要使用 typescript 實現(xiàn)一個 get 函數(shù)來獲取它的屬性值

const data = {
  a: 3,
  hello: 'world'
}

function get(o: object, name: string) {
  return o[name]
}

我們剛開始可能會這么寫,不過它有很多缺點

  • 無法確認(rèn)返回類型:這將損失 ts 最大的類型校驗功能
  • 無法對 key 做約束:可能會犯拼寫錯誤的問題

這時可以使用 keyof 來加強 get 函數(shù)的類型功能,有興趣的同學(xué)可以看看 _.get 的 type 標(biāo)記以及實現(xiàn)

function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
  return o[name]
}

02 Required & Partial & Pick

既然了解了 keyof,可以使用它對屬性做一些擴展, 如實現(xiàn) PartialPickPick 一般用在 _.pick

type Partial<T> = {
  [P in keyof T]?: T[P];
};

type Required<T> = {
  [P in keyof T]-?: T[P];
};

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

interface User {
  id: number;
  age: number;
  name: string;
};

// 相當(dāng)于: type PartialUser = { id?: number; age?: number; name?: string; }
type PartialUser = Partial<User>

// 相當(dāng)于: type PickUser = { id: number; age: number; }
type PickUser = Pick<User, "id" | "age">

這幾個類型已內(nèi)置在 Typescript 中

03 Condition Type

類似于 js 中的 ?: 運算符,可以使用它擴展一些基本類型

T extends U ? X : Y

type isTrue<T> = T extends true ? true : false
// 相當(dāng)于 type t = false
type t = isTrue<number>

// 相當(dāng)于 type t = false
type t1 = isTrue<false>

04 never & Exclude & Omit

官方文檔對 never 的描述如下

the never type represents the type of values that never occur.

結(jié)合 neverconditional type 可以推出很多有意思而且實用的類型,比如 Omit

type Exclude<T, U> = T extends U ? never : T;

// 相當(dāng)于: type A = 'a'
type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>

結(jié)合 Exclude 可以推出 Omit 的寫法

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

interface User {
  id: number;
  age: number;
  name: string;
};

// 相當(dāng)于: type PickUser = { age: number; name: string; }
type OmitUser = Omit<User, "id">

05 typeof

顧名思義,typeof 代表取某個值的 type,可以從以下示例來展示他們的用法

const a: number = 3

// 相當(dāng)于: const b: number = 4
const b: typeof a = 4

在一個典型的服務(wù)端項目中,我們經(jīng)常需要把一些工具塞到 context 中,如config,logger,db models, utils 等,此時就使用到 typeof。

import logger from './logger'
import utils from './utils'

interface Context extends KoaContect {
  logger: typeof logger,
  utils: typeof utils
}

app.use((ctx: Context) => {
  ctx.logger.info('hello, world')

  // 會報錯,因為 logger.ts 中沒有暴露此方法,可以最大限度的避免拼寫錯誤
  ctx.loger.info('hello, world')
})

06 is

在此之前,先看一個 koa 的錯誤處理流程,以下是對 error 進(jìn)行集中處理,并且標(biāo)識 code 的過程

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    let code = 'BAD_REQUEST'
    if (err.isAxiosError) {
      code = `Axios-${err.code}`
    } else if (err instanceof Sequelize.BaseError) {

    }
    ctx.body = {
      code
    }
  }
})

err.code 處,會編譯出錯,提示 Property 'code' does not exist on type 'Error'.ts(2339)

此時可以使用 as AxiosError 或者 as any 來避免報錯,不過強制類型轉(zhuǎn)換也不夠友好

if ((err as AxiosError).isAxiosError) {
  code = `Axios-${(err as AxiosError).code}`
}

此時可以使用 is 來判定值的類型

function isAxiosError (error: any): error is AxiosError {
  return error.isAxiosError
}

if (isAxiosError(err)) {
  code = `Axios-${err.code}`
}

GraphQL 的源碼中,有很多諸如此類的用法,用以標(biāo)識類型

export function isType(type: any): type is GraphQLType;

export function isScalarType(type: any): type is GraphQLScalarType;

export function isObjectType(type: any): type is GraphQLObjectType;

export function isInterfaceType(type: any): type is GraphQLInterfaceType;

07 interface & type

interfacetype 的區(qū)別是什么?可以參考以下 stackoverflow 的問題

stackoverflow.com/questions/3…

一般來說,interfacetype 區(qū)別很小,比如以下兩種寫法差不多

interface A {
  a: number;
  b: number;
};

type B = {
  a: number;
  b: number;
}

其中 interface 可以如下合并多個,而 type 只能使用 & 類進(jìn)行連接。

interface A {
    a: number;
}

interface A {
    b: number;
}

const a: A = {
    a: 3,
    b: 4
}

08 Record & Dictionary & Many

這幾個語法糖是從 lodash 的 types 源碼中學(xué)到的,平時工作中的使用頻率還挺高。

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

interface Dictionary<T> {
  [index: string]: T;
};

interface NumericDictionary<T> {
  [index: number]: T;
};

const data:Dictionary<number> = {
  a: 3,
  b: 4
}

09 使用 const enum 維護(hù)常量表

相比使用字面量對象維護(hù)常量,const enum 可以提供更安全的類型檢查

// 使用 object 維護(hù)常量
const TODO_STATUS {
  TODO: 'TODO',
  DONE: 'DONE',
  DOING: 'DOING'
}
// 使用 const enum 維護(hù)常量
const enum TODO_STATUS {
  TODO = 'TODO',
  DONE = 'DONE',
  DOING = 'DOING'
}

function todos (status: TODO_STATUS): Todo[];

todos(TODO_STATUS.TODO)

10 VS Code Tips & Typescript Command

使用 VS Code 有時會出現(xiàn),使用 tsc 編譯時產(chǎn)生的問題與 vs code 提示的問題不一致

找到項目右下角的 Typescript 字樣,右側(cè)顯示它的版本號,可以點擊選擇 Use Workspace Version,它表示與項目依賴的 typescript 版本一直。

或者編輯 .vs-code/settings.json

{
  "typescript.tsdk": "node_modules/typescript/lib"
}

11 Typescript Roadmap

最后一條也是最重要的一條,翻閱 Roadmap,了解 ts 的一些新的特性與 bug 修復(fù)情況。

相關(guān)文章

最新評論