跳至主要內容

BFE-TS TypeScript类型体操练习 Easy 1-10

YihuiTypeScript大约 3 分钟

BFE-TS TypeScript类型体操练习 Easy 1-10

题目来自TypeScript题目 | BFE.dev - 前端刷题,准备前端面试拿到心仪的Offeropen in new window,总共60题,带你完爆类型体操!

Utility types 内置工具类型实现

  1. 实现Partial

    Partial<T>返回一个包含所有T的子集的type。

    type Foo = {
      a: string
      b: number
      c: boolean
    }// below are all validconst a: MyPartial<Foo> = {}const b: MyPartial<Foo> = {
      a: 'BFE.dev'
    }const c: MyPartial<Foo> = {
      b: 123
    }const d: MyPartial<Foo> = {
      b: 123,
      c: true
    }const e: MyPartial<Foo> = {
      a: 'BFE.dev',
      b: 123,
      c: true
    }
    

    答案:

    type Partial<T> = {
        [P in keyof T]?: T[P];
    };
    
  2. 实现Required

    Partial<T>正好相反, Required<T>会将所有的属性设为required。

    // all properties are optional
    type Foo = {
      a?: string
      b?: number
      c?: boolean
    }
    ​
    ​
    const a: MyRequired<Foo> = {}
    // Errorconst b: MyRequired<Foo> = {
      a: 'BFE.dev'
    }
    // Errorconst c: MyRequired<Foo> = {
      b: 123
    }
    // Errorconst d: MyRequired<Foo> = {
      b: 123,
      c: true
    }
    // Errorconst e: MyRequired<Foo> = {
      a: 'BFE.dev',
      b: 123,
      c: true
    }
    // valid
    

    答案:

    type Required<T> = {
        [P in keyof T]-?: T[P];
    };
    
  3. 实现Readonly

    答案:

    type Readonly<T> = {
        readonly [P in keyof T]: T[P];
    };
    
  4. 实现Record

    Record<K, V>返回一个key是K值是V的object type。

    type Key = 'a' | 'b' | 'c'const a: Record<Key, string> = {
      a: 'BFE.dev',
      b: 'BFE.dev',
      c: 'BFE.dev'
    }
    a.a = 'bigfrontend.dev' // OK
    a.b = 123 // Error
    a.d = 'BFE.dev' // Errortype Foo = MyRecord<{a: string}, string> // Error
    

    答案:

    type Record<K extends keyof any, T> = {
        [P in K]: T;
    };
    
  5. 实现Pick

    Pick<T, K>,正如其名所示,将从T中抽选出K中含有的属性然后返回一个新的type。

    type Foo = {
      a: string
      b: number
      c: boolean
    }type A = MyPick<Foo, 'a' | 'b'> // {a: string, b: number}
    type B = MyPick<Foo, 'c'> // {c: boolean}
    type C = MyPick<Foo, 'd'> // Error
    

    答案:

    type Pick<T, K extends keyof T> = {
        [P in K]: T[P];
    };
    
  6. 实现Omit

    Omit<T, K>返回一个从T的属性中剔除掉K过后的type。

    type Foo = {
      a: string
      b: number
      c: boolean
    }type A = MyOmit<Foo, 'a' | 'b'> // {c: boolean}
    type B = MyOmit<Foo, 'c'> // {a: string, b: number}
    type C = MyOmit<Foo, 'c' | 'd'> // {a: string, b: number}
    

    答案:

    type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
    
  7. 实现Exclude

    Exclude<T, K>返回一个从T中去掉能代入K的成员后的type。

    type Foo = 'a' | 'b' | 'c'type A = MyExclude<Foo, 'a'> // 'b' | 'c'
    type B = MyExclude<Foo, 'c'> // 'a' | 'b
    type C = MyExclude<Foo, 'c' | 'd'>  // 'a' | 'b'
    type D = MyExclude<Foo, 'a' | 'b' | 'c'>  // never
    

    答案:

    type Exclude<T, U> = T extends U ? never : T;
    
  8. 实现Extract

    和Exclude正好相反, Extract<T, U>返回T中可以代入到U的成员所组成的type。

    type Foo = 'a' | 'b' | 'c'type A = MyExtract<Foo, 'a'> // 'a'
    type B = MyExtract<Foo, 'a' | 'b'> // 'a' | 'b'
    type C = MyExtract<Foo, 'b' | 'c' | 'd' | 'e'>  // 'b' | 'c'
    type D = MyExtract<Foo, never>  // never
    

    答案:

    type Extract<T, U> = T extends U ? T : never;
    
  9. 实现NonNullable

    剔除 null | undefined 类型,表明非空

    答案:

    type NonNullable<T> = T extends null | undefined ? never : T;
    
  10. 实现Parameters

    对于function type T, Parameters<T> 返回一个由其参数type组成的tuple type。

    type Foo = (a: string, b: number, c: boolean) => stringtype A = MyParameters<Foo> // [a:string, b: number, c:boolean]
    type B = A[0] // string
    type C = MyParameters<{a: string}> // Error
    

    答案:

    type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;