typescript - 泛型类型不解析为联合
问题描述
以下代码错误:
class Base { }
class Child1 extends Base {
child1Fn() {}
static deserialize(bytes: Uint8Array): Child1 {
return new Child1();
}
}
class Child2 extends Base {
child2Fn() {}
static deserialize(bytes: Uint8Array): Child2 {
return new Child2();
}
}
const childMap = {
"child1": Child1.deserialize,
"child2": Child2.deserialize
}
function deserialize<T>(
data: { name: string, bytes: Uint8Array },
deserializeMap: Record<string, (bytes: Uint8Array) => T>
): T {
const deserializeFn = deserializeMap[data.name];
if (deserializeFn) {
return deserializeFn(data.bytes)
}
}
function deserializeChildMap(data: { name: string, bytes: Uint8Array }) {
return deserialize(data, childMap)
}
我最终得到了错误:
Argument of type '{ "child1": (bytes: Uint8Array) => Child1; "child2": (bytes: Uint8Array) => Child2; }' is not assignable to parameter of type 'Record<string, (bytes: Uint8Array) => Child1>'.
Property '"child2"' is incompatible with index signature.
Type '(bytes: Uint8Array) => Child2' is not assignable to type '(bytes: Uint8Array) => Child1'.
Property 'child1Fn' is missing in type 'Child2' but required in type 'Child1'.
它看起来将类型解析为T
childMap (Child1) 中的第一个返回值。理想情况下,我想T
解决Child1 | Child2
. 有没有办法做到这一点?
解决方案
可以做到,但需要更多的泛型类型参数:
class Base { }
class Child1 extends Base {
child1Fn() { }
static deserialize(bytes: Uint8Array): Child1 {
return new Child1();
}
}
class Child2 extends Base {
child2Fn() { }
static deserialize(bytes: Uint8Array): Child2 {
return new Child2();
}
}
const childMap = {
"child1": Child1.deserialize,
"child2": Child2.deserialize
}
function deserialize<TName extends string, TMap extends Record<TName, (bytes: Uint8Array) => any>>(
data: { name: TName, bytes: Uint8Array },
deserializeMap: TMap
): ReturnType<TMap[TName]> {
const deserializeFn = deserializeMap[data.name];
if (deserializeFn) {
return deserializeFn(data.bytes)
}
}
function deserializeChildMap<TName extends keyof typeof childMap>(data: { name: TName, bytes: Uint8Array }): ReturnType<typeof childMap[TName]> {
return deserialize(data, childMap)
}
let c1 = deserializeChildMap({ name: "child1", bytes: null!}) // child1
let c2 = deserializeChildMap({ name: "child2", bytes: null!}) // child2
推荐阅读
- gremlin - Gremlin bothE() 是否双重计算边缘?
- android-studio - 使用ndk在android studio中启动应用程序时安装失败?
- java - 将大写日期解析为 LocalDate
- yii - Yii 1.1 urlManager .php?param=重定向
- python - Python 库无法在使用网络摄像头捕获的两个移位图像之间进行详细的图像比较
- ajax - Primefaces SelectOneRadio 结果页面有变化
- jquery - 如何修复错误 TeamsController#load_users 缺少此请求格式和变体的模板
- android - 处理(许多)后堆栈
- sql - 以下场景的 SQL 查询
- python - 使用 Selenium + Python 循环链接并从结果页面中抓取数据