首页 > 解决方案 > TypeScript:如何从类型中仅提取类型数组的键和值

问题描述

我想提出一些条件来仅从值为数组的对象中提取属性。

例如:

type Person = {
   name: string
   addresses: Address[]
   age: number
   phoneNumbers: PhoneNumber[]
}

PullOutArrays<Person> => {
   phoneNumbers: PhoneNumber[]
   addresses: Address[]
}

我尝试过这样的事情无济于事:

type PulledOutArrays<T extends Record<string, unknown>> = {
  [K in keyof T]: T[K] extends unknown[] ? T[K] : never
}

标签: typescript

解决方案


这个 GitHub 问题中抄袭:

type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];

type FilteredProperties<T, U> = { [K in FilteredKeys<T, U>]: T[K]; };

type PullOutArrays<T> = FilteredProperties<T, unknown[]>;

type Person = {
  name: string
  addresses: string[]
  age: number
  phoneNumbers: number[]
}

type PersonKeys = FilteredKeys<Person, unknown[]>;

// "addresses" | "phoneNumbers"

type PersonArrays = PullOutArrays<Person>;

// {
//    addresses: string[];
//    phoneNumbers: number[];
// }

正如您可能从最初的尝试中看到的那样,映射条件后最终得到的结果是:

{ [P in keyof T]: T[P] extends U ? P : never }

是一个包含所有属性键的接口,但将非数组类型更改为never,显然是因为 TS 最初并未检查分配给属性键的类型是什么。通过在末尾添加索引,您可以强制编译器读取属性的值并最终从结果中忽略它。

使用生成的联合,您可以在原始接口上从该联合创建新的映射类型。


推荐阅读