[英]Infer subclass property type from base class generic in typescript
class A<T>
{
some: { [K in keyof T]: (x: T[K]) => T[K] }
}
interface IB {
b: number
}
class B<T extends IB> extends A<T>
{
constructor()
{
super()
/**
* Type '{ b: (x: T["b"]) => number; }'
* is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'.
*/
this.some = {
b: x => 2*x
}
}
}
interface IC {
b: number
c: boolean
}
class C<T extends IC> extends B<T>
{
constructor()
{
super()
/**
* Type '{ b: (x: T["b"]) => number; c: (x: T["c"]) => boolean; }'
* is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'
*/
this.some = {
b: x => 4*x,
c: x => !x
}
}
}
你好。 我试图在基类“ A”中设置通用约束,以自动推断派生类中“某些”属性的类型。 不幸的是,我不明白为什么会出现如上所述的TS错误。 从我的角度来看,一切似乎都还可以。
谢谢!
如果我这样做,该怎么办?
const b = new B<{ b: 3, z: string }>();
如您所见,我传入了{ b: 3, z: string }
,这是可以接受的,因为它扩展了{ b: number }
。 所以这意味着b.some.b
应该是(x: 3) => 3
。 这也意味着b.some.z
应该是(x: string) => string
。 B
的实现是否是真的? 没有; b.some.b
实际上是(x: 3) => number
,而b.some.z
是未定义的。 因此,编译器警告您是有道理的。
首先,让我们处理z: string
问题。 也许在A
您希望其中some
的属性是可选的,如下所示:
class A<T>
{
some: {[K in keyof T]?: (x: T[K]) => T[K]}
}
这将使您的B
和C
构造函数可以初始化some
而不必了解额外的属性。
现在,关于b: 3
。 如果您想允许某人扩展number
,那么唯一可以使用的安全方法就是身份验证功能:
this.some = {};
this.some.b = x => x; // okay
但可能您不希望任何人传递比b
类型更具体的number
。 不幸的是,没有阻止它的好方法。 因此,很好地证明,用户只能传递b
可以为任何number
类型。 在这种情况下,你只是需要告诉编译器不要担心,通过声称this
是类型B<IB>
this.some = {};
(this as B<IB>).some.b = x => 2 * x; // okay
可以为您的C
类进行类似的修复。 希望能有所帮助; 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.