如何在TypeScript中从数组中提取类型?

47
有没有一种在 TypeScript 中声明类型的方法,可以“提取”数组的内部类型?
例如:
假设我已经在我的代码库中有这样的东西:
export interface Cache {
    events: Event[],
    users: User[]
}
type CacheType = Event[] | User[];

//or maybe: 
//   type TypeOfProperty = T[keyof T];
//   type CacheType = TypeOfProperty<Cache>; 

我想要的是与以下内容等效的东西:
type InnerCacheType = Event | User;

但是,如果我每次添加CacheCacheType时都要手动重新输入,那么有没有办法自动完成呢?

在Typescript中是否可能实现这一点?

3个回答

62
这在Typescript 2.8+是可能的。您可以声明一个Unpacked<T>类型,如下所示:
type Unpacked<T> = T extends (infer U)[] ? U : T;

现在,您可以做到以下事情。
type InnerCacheType = Unpacked<CacheType>; // Event | User

这是在文档中给出的Unpacked类型的简明定义。

7
Unpacked<T>类型定义:如果T是Array<infer U>类型,则Unpacked<T>为U类型,否则如果T是ReadonlyArray<infer U>类型,则Unpacked<T>为U类型,否则Unpacked<T>为T类型。该定义同样适用于ReadonlyArray类型。 - Sibelius Seraphini

58
这也可以通过类型查询来实现。例如:
type CacheType = Event[] | User[];
type InnerCacheType = CacheType[number]; // Event | User

TS Playground

如果您查看来自ts开发团队的评论

您可以编写

const t: Array<string>[number] = "hello";

作为编写const t: string的迂回方式。

所以这个结论总是成立的。


5
假设您可以使用TypeScript 2.1或更高版本,否则无法实现您要寻找的内容。
同时,请注意您默认所有Cache接口的属性都是数组。如果不是这种情况,您的问题就变得没有意义了,因此我也会做出这个假设。
一般来说,CacheType可以写成:
type CacheType = Cache[typeof Cache];

包括所有继承属性。得到的类型等同于Event[] | User[],但是从这种联合类型中提取数组组件是不可行的。

解决方案是使用映射类型。你所寻找的InnerCacheType可以写成

type InnerCacheType = MappedCacheType[typeof MappedCacheType];

在哪里

type MappedCacheType = { [P in keyof Cache]: Cache[P][0]; };

事实上,最后一种类型等同于
{ events: Event; users: User; }

请注意,TypeScript 保持与原始名称相同。
总结一下,在不考虑使用情况的情况下,表示数组类型 T 的组件类型的方式是 T[0]。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接