1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        typescript 高級技巧

        共 5149字,需瀏覽 11分鐘

         ·

        2021-08-09 21:18

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

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

        01 keyof

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

        interface Point {    x: number;    y: number;}
        // type keys = "x" | "y"type keys = keyof Point;

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

        const data = {  a: 3,  hello: 'world'}
        function get(o: object, name: string) { return o[name]}

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

        1. 無法確認返回類型:這將損失 ts 最大的類型校驗功能
        2. 無法對 key 做約束:可能會犯拼寫錯誤的問題

        這時可以使用 keyof 來加強 get 函數(shù)的類型功能,有興趣的同學可以看看 _.get 的 type 標記以及實現(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) PartialPick,Pick 一般用在 _.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;};
        // 相當于: type PartialUser = { id?: number; age?: number; name?: string; }type PartialUser = Partial<User>
        // 相當于: type PickUser = { id: number; age: number; }type PickUser = Pick<User, "id" | "age">

        這幾個類型已內置在 Typescript 中

        03 Condition Type

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

        T extends U ? X : Y
        type isTrue<T> = T extends true ? true : false// 相當于 type t = falsetype t = isTrue<number>
        // 相當于 type t = falsetype t1 = isTrue<false>

        04 never & Exclude & Omit

        官方文檔對 never 的描述如下

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

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

        type Exclude<T, U> = T extends U ? never : T;
        // 相當于: type A = 'a'type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>

        結合 Exclude 可以推出 Omit 的寫法

        type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
        interface User { id: number; age: number; name: string;};
        // 相當于: type PickUser = { age: number; name: string; }type OmitUser = Omit<User, "id">

        05 typeof

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

        const a: number = 3
        // 相當于: const b: number = 4const b: typeof a = 4

        在一個典型的服務端項目中,我們經(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 進行集中處理,并且標識 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 來避免報錯,不過強制類型轉換也不夠友好

        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 的源碼中,有很多諸如此類的用法,用以標識類型

        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 的問題

        https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types

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

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

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

        interface A {    a: number;}
        interface A { b: number;}
        const a: A = { a: 3, b: 4}

        08 Record & Dictionary & Many

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

        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 維護常量表

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

        // 使用 object 維護常量const TODO_STATUS {  TODO: 'TODO',  DONE: 'DONE',  DOING: 'DOING'}
        // 使用 const enum 維護常量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 字樣,右側顯示它的版本號,可以點擊選擇 Use Workspace Version,它表示與項目依賴的 typescript 版本一直。

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

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

        11 Typescript Roadmap

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

        Typescript Roadmap

        參考

        • https://www.typescriptlang.org/docs/handbook/advanced-types.html
        • https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html
        • https://moin.world/2017/06/18/10-typescript-features-you-might-not-know/
        瀏覽 23
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线激情成人网 | 久久最新网址 | 黄色一级视频在线观看 | 欧美黑人疯狂性受xxxxx野外 | 日韩一二三级 | 大香蕉伊人视频在线观看 | 午夜福利一区二区三区免费 | 婷婷爱爱 | 高潮胡言乱语对白刺激40分钟 | 欧美V∧|