打字稿多类型映射
Typescript multiple type mapping
我想像这样做一些类型映射:
有些模块带有id
和actions
,我想合并所有的动作方法并重新映射其方法名称添加${id}/
前缀,示例代码在这里:
const m1 = {
id: 'm1',
actions: {
down(id: string) {
return true;
},
up(n: number) {
return 0;
}
}
}
const m2 = {
id: 'm2',
actions: {
play(id: string) {
return true;
},
go(n: number) {
return 0;
}
}
}
type MyModule = ??
// should return :
// MyModule = {
// 'm1/down': (id: string) => boolean,
// 'm1/up': (n: number) => number;
// 'm2/play': (id: string) => boolean;
// 'm2/go': (n: number) => number;
// }
这在打字稿中可能吗?
您可以在较新版本的 Typescript 中使用映射类型和模板文字类型来执行此操作:
type ModuleDefnition = {
id: string,
actions: Record<string, (...a: any[]) => any>
}
type Module<T extends ModuleDefnition> = {} & {
[P in keyof T['actions'] & string as `${T['id']}/${P}`]: T['actions'][P]
}
type MyModule = Module<typeof m1> & Module<typeof m2>
模块定义的唯一变化是id
你需要确保你有一个字符串文字类型
如果您有未知数量的模块或者您想使用函数创建模块,您也可以使用 UnionToIntersection
(来自 )。
type DistributeModule<T extends ModuleDefnition> = T extends T ? Module<T> : never;
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
function merge<T extends ModuleDefnition[]>(...a: T):UnionToIntersection<DistributeModule<T[number]>> {
return null!;
}
let myModule = merge(m1, m2)
我想像这样做一些类型映射:
有些模块带有id
和actions
,我想合并所有的动作方法并重新映射其方法名称添加${id}/
前缀,示例代码在这里:
const m1 = {
id: 'm1',
actions: {
down(id: string) {
return true;
},
up(n: number) {
return 0;
}
}
}
const m2 = {
id: 'm2',
actions: {
play(id: string) {
return true;
},
go(n: number) {
return 0;
}
}
}
type MyModule = ??
// should return :
// MyModule = {
// 'm1/down': (id: string) => boolean,
// 'm1/up': (n: number) => number;
// 'm2/play': (id: string) => boolean;
// 'm2/go': (n: number) => number;
// }
这在打字稿中可能吗?
您可以在较新版本的 Typescript 中使用映射类型和模板文字类型来执行此操作:
type ModuleDefnition = {
id: string,
actions: Record<string, (...a: any[]) => any>
}
type Module<T extends ModuleDefnition> = {} & {
[P in keyof T['actions'] & string as `${T['id']}/${P}`]: T['actions'][P]
}
type MyModule = Module<typeof m1> & Module<typeof m2>
模块定义的唯一变化是id
你需要确保你有一个字符串文字类型
如果您有未知数量的模块或者您想使用函数创建模块,您也可以使用 UnionToIntersection
(来自
type DistributeModule<T extends ModuleDefnition> = T extends T ? Module<T> : never;
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
function merge<T extends ModuleDefnition[]>(...a: T):UnionToIntersection<DistributeModule<T[number]>> {
return null!;
}
let myModule = merge(m1, m2)