给定以下类型:
type Person = {
name: string;
};
type Family = {
parent: Person;
children: Person[];
};
我想定义另一个类型Aggregated<T>
,它将自动生成以下类型:
type FamilyAggregatedExpected = {
parent: Person[];
children: Aggregated<Person>[];
};
:
- 对于非列表属性,新类型包含与原始属性 类型相同的值数组
- 对于列表属性,新类型包含一个类型为
Aggregated<T>
的值数组。
我使用列表属性有困难。
到目前为止,我已经试过了:
export type Aggregated<T> = {
[key in keyof T]: T[key] extends any[] ? Aggregated<any>[] : T[key][];
};
,但不输入Aggregated
类型参数。试图解决这个问题:
export type Aggregated<T,U = never> = {
[key in keyof T]: T[key] extends U[] ? Aggregated<U>[] : T[key][];
};
不能作为extends U[]
工作,总是失败。
我如何提取列表元素类型,以便我可以将其传递给Aggregated<T>
?
Stackblitz: https://stackblitz.com/edit/so-conditional-types?file=index.ts
有几种方法可以做到这一点;看起来最接近你的方法是使用infer
声明在条件类型中获得类型推断:
type Aggregated<T> = {
[K in keyof T]: T[K] extends Array<infer U> ? Aggregated<U>[] : T[K][];
};
对于T
的每个属性键K
,我们检查T[K]
是否为Array<infer U>
类型的数组。如果是,则U
将是数组的元素类型,我们可以将其传递给Aggregated
。让我们确保它能工作:
type FamilyAggregated = Aggregated<Family>
/* type FamilyAggregated = {
parent: Person[];
children: Aggregated<Person>[];
} */
看起来不错。
Playground链接到代码