【发布时间】:2018-11-20 20:30:00
【问题描述】:
我有一个基本类型Base,我想创建一个对象,该对象包含接收Base 的某些子类型(在本例中为ExtendsBaseA 或ExtendsBaseB)的函数并将其映射到另一种类型C .
我尝试将 “Base 的某些子类型” 声明为 <T extends Base>,但类型检查失败并显示以下内容:
类型 '(baseA: ExtendsBaseA) => C' 不能分配给类型 '(base: T) => C'。
参数'base'和'baseA'的类型不兼容。
类型“T”不能分配给类型“ExtendsBaseA”。
类型“Base”不可分配给类型“ExtendsBaseA”。
“Base”类型中缺少属性“b”。
片段
interface Base {
a: string
}
interface ExtendsBaseA extends Base {
b: string
}
interface ExtendsBaseB extends Base {
c: string
}
interface C {}
class Foo {
private readonly handlers: {
[key: string]: <T extends Base> (base: T) => C
}
constructor() {
this.handlers = {
'bar' : this.handler
}
}
handler(baseA: ExtendsBaseA): C {
return <C>null;
}
}
关于如何解决这个问题的任何想法?
编辑:奇怪的是,如果我改变:
[key: string]: <T extends Base> (base: T) => C
到:
[key: string]: (base: Base) => C
它可以在操场上工作,但当我在本地 Typescript 安装上尝试时却不行。 (都是2.9.1)
【问题讨论】:
-
在 Playground 中打开
strictFunctionTypes以查看错误。 -
您打算如何使用
handlers?如果每个属性都是一个只处理Base的some 子类型而不是Base的all 子类型的函数,那么就无法使用任何参数调用它(因为您永远不知道您拥有的Base对象是否是该函数的“正确”对象)。要么让你的函数接受Base的所有 子类型,要么采用一种类型安全的方式将每个Base分派给适当的处理函数。如果你能详细说明你打算如何实际使用handlers,我可能会提出一个具体的建议。 -
@jcalz 感谢游乐场提示。所以我有不同的
Base子类型,我想以不同的方式处理,Base上的type字符串属性可以帮助我唯一区分它们。我想使用Base.type字符串调度适当的handler函数:this.handlers[obj.type](obj)。 -
@jcalz 我猜这些被称为 "discriminated unions" 并且打字稿可以使用类型保护来处理它们。但是在这种情况下,我只想阻止类型系统妨碍我,让我通过索引地图来做到这一点。我想我可以做到
[key: string]: (base: any) => C,但any感觉太宽松了,因为我的函数参数总是Base的子类型。只是觉得会有办法做到这一点
标签: typescript generics types