简而言之:
如何使用 Typescript 类型的系统声明一个作为类型参数的泛型接口
- 组的一种类型
G
(属于一个组的所有属性) - 组中某个项目的类型
I
(一个项目的所有属性,其中一个组有几个) N
中的一种属性类型G
,它的值是该组G[N]
的项目数组I[]
并让生成的接口类型是一个组 G,其属性 N 被键入到项目 I 的数组中,同时在生成的类型中还包括 G 的所有其他属性。
到目前为止我尝试过的
修订 #2(成功)
在阅读了一些关于计算索引类型(正确的名称?)及其局限性之后,我想出了这种方法:
type GroupOfItems<Group, Item, GroupOn extends keyof Group> = {
[n in GroupOn]: Item[];
}
type A = {a: any, children: B[]};
type B = {b: number};
let obj: GroupOfItems<A, B, 'children'> & Omit<A, 'children'>;
我使用联合类型来组合通用“组”接口和“其他”属性,从而产生我想要的结构的完全类型检查对象。在这个操场上看看
修订 #1
第一个答案告诉我我有一个语法错误。它提供了一个具有 3 个类型参数的有效接口。但是,生成的类型缺少项目数组以外的任何组属性。
我的下一次尝试,似乎是无效的打字稿(见操场):
type GroupOfItems<Group, Item, GroupProp extends keyof Group> = {
[OtherProp in keyof Omit<Group, GroupProp>]: Group[OtherProp];
[n in GroupProp]: Item[];
}
我天真的第一次尝试:
interface GroupOfItems<GroupType, ItemType, NameOfItemsProp extends keyof G> {
[key: NameOfItemsProp]: ItemType[];
}
但是,正如您在这个 TS Playground中看到的那样,Typescript 编译器对此并不满意,我想不出办法。
这个结构的具体用法
假设以下类型
interface Movie { // An example Item
id: number,
title: string,
releaseYear: number,
// ... more movie properties
}
interface MovieList { // An example Group
id: number,
description: string,
// ... more list properties
movies: Movie[], // This property holds the group of items
}
已定义,我想创建一个泛型类型GroupOfItems<MovieList, Movie, 'movies'>
,该类型应映射到类似的结构
{
id: 0,
description: 'A collection of funny movies'
totalRuntimeInSecs: 9815,
// ... all other movielist properties
movies: [
{
id: 0,
title: 'Blazing Saddles',
releaseYear: 1974,
// ...
}
]
}
但是,我也希望具体类型GroupOfItems<Playlist, Song, 'songs'>
(假设Playlist
和Song
定义)与
{
playlistId: 0,
playlistName: string,
playlistDescription: string,
//... more playlist props
songs: Song[] // This property holds the item array
}
提问的动机
我正在尝试实现一个通用数据源类,该类可以对其数据进行分组并切换项目组的可见性。虽然输入数据的结构是不变的,但保存组项目的属性名称在现有接口中可能不同。