[TypeScript] Type Challenges #2946 - ObjectEntries

35 阅读1分钟

题目描述

Implement the type version of Object.entries

For example

interface Model {
  name: string;
  age: number;
  locations: string[] | null;
}
type modelEntries = ObjectEntries<Model> // ['name', string] | ['age', number] | ['locations', string[] | null];

题解

// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'

interface Model {
  name: string
  age: number
  locations: string[] | null
}

type ModelEntries = ['name', string] | ['age', number] | ['locations', string[] | null]

type cases = [
  Expect<Equal<ObjectEntries<Model>, ModelEntries>>,
  Expect<Equal<ObjectEntries<Partial<Model>>, ModelEntries>>,
  Expect<Equal<ObjectEntries<{ key?: undefined }>, ['key', undefined]>>,
  Expect<Equal<ObjectEntries<{ key: undefined }>, ['key', undefined]>>,
  Expect<Equal<ObjectEntries<{ key: string | undefined }>, ['key', string | undefined]>>,
]


// ============= Your Code Here =============
type ObjectEntries<
  T, 
  P = keyof T
> = 
  P extends keyof T 
    ? [P, Required<T>[P] extends [never] 
       ? undefined 
       : Required<T>[P]] 
    : undefined;

条件类型

type ObjectEntries<
  T, 
  P = keyof T
> = 
  P extends keyof T 
    ? [P, Required<T>[P] extends [never] 
       ? undefined 
       : Required<T>[P]] 
    : undefined;
  • 泛型参数:

    • T:目标对象

    • P = keyof T:默认为T的所有键,用于分布式条件判断

  • 条件类型:

    • P extends keyof T

      • 如果PT的键:

        • [P, Required<T>[P] extends [never] ? undefined : Required<T>[P]]

          • 元组类型:将键P和值Required<T>[P]组合成元组

          • 处理never类型:

            • Required<T>[P]:通过Required去除值的可选性,确保值类型为非可选类型

            • extends [never] ? undefined:如果去除可选性后的值类型为never,则用undefined替代,否则保留原值类型

      • 如果P不是T的键,返回undefined