我try 使用从相同父类继承的2个类(不是这些类的实例)作为WeakMap的键.这两个派生类的构造函数具有不同的签名.
因此,我的代码如下所示:
class Base{
constructor(args:{}){}
}
class A extends Base{
constructor(args:{a:string}){
super(args)
}
}
class B extends Base{
constructor(args:{b:number}){
super(args)
}
}
const myMap:WeakMap<new(args:object)=>Base, number> = new WeakMap([
// [Base, 0], I will explain after why there is that commented line.
[A, 1],
[B, 2]
])
输出结果为:
No overload matches this call.
Overload 1 of 2, '(iterable: Iterable<readonly [typeof A, number]>): WeakMap<typeof A, number>', gave the following error.
Argument of type '([typeof A, number] | [typeof B, number])[]' is not assignable to parameter of type 'Iterable<readonly [typeof A, number]>'.
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
Type 'IteratorResult<[typeof A, number] | [typeof B, number], any>' is not assignable to type 'IteratorResult<readonly [typeof A, number], any>'.
Type 'IteratorYieldResult<[typeof A, number] | [typeof B, number]>' is not assignable to type 'IteratorResult<readonly [typeof A, number], any>'.
Type 'IteratorYieldResult<[typeof A, number] | [typeof B, number]>' is not assignable to type 'IteratorYieldResult<readonly [typeof A, number]>'.
Type '[typeof A, number] | [typeof B, number]' is not assignable to type 'readonly [typeof A, number]'.
Type '[typeof B, number]' is not assignable to type 'readonly [typeof A, number]'.
Type at position 0 in source is not compatible with type at position 0 in target.
Type 'typeof B' is not assignable to type 'typeof A'.
Types of construct signatures are incompatible.
Type 'new (args: { a: number; }) => B' is not assignable to type 'new (args: { a: string; }) => A'.
Types of parameters 'args' and 'args' are incompatible.
Type '{ a: string; }' is not assignable to type '{ a: number; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type 'number'.
Overload 2 of 2, '(entries?: readonly (readonly [typeof A, number])[] | null | undefined): WeakMap<typeof A, number>', gave the following error.
Type 'typeof B' is not assignable to type 'typeof A'.
Argument of type 'typeof A' is not assignable to parameter of type 'new (args: object) => Base'.
Types of construct signatures are incompatible.
Type 'new (args: { a: string; }) => A' is not assignable to type 'new (args: object) => Base'.
Types of parameters 'args' and 'args' are incompatible.
Property 'a' is missing in type '{}' but required in type '{ a: string; }'.
在我的代码中,我注释了一行:
const myMap:WeakMap<new(args:object)=>Base, number> = new WeakMap([
// [Base, 0],
[A, 1],
[B, 2]
])
如果我取消对该行的注释,则不会出现错误.至少在我不使用我的 map ^^‘的时候没有错误.如果我调用Map的任何方法,比如myMap.get(A)
,我会得到一个错误:
Argument of type 'typeof A' is not assignable to parameter of type 'new (args: object) => Base'.
Types of construct signatures are incompatible.
Type 'new (args: { a: string; }) => A' is not assignable to type 'new (args: object) => Base'.
Types of parameters 'args' and 'args' are incompatible.
Property 'a' is missing in type '{}' but required in type '{ a: string; }'.
有什么诀窍?我的意思是类只是用作映射中的键.我不在乎它的签名.
UPDATE : Add a third sub class with a signature even more different :个
会员jcalz给了我一个解决这个问题的方案(阅读第一条 comments ).它看起来很棒,但我想知道是否有更通用的解决方案. 索引中,只有当我所有子类都使用单个参数时,才能使用解决方案(使用Never关键字).但是,如果我有一个类,它的构造函数比其他类使用了更多的参数,该怎么办呢?因此,此时,我的代码如下所示:
class Base {
constructor(args: {}) { }
}
class A extends Base {
constructor(args: { a: string }) {
super(args)
}
}
class B extends Base {
constructor(args: { b: number }) {
super(args)
}
}
class C extends Base{
constructor(args:{}, other:number){
super(args)
}
}
有没有办法做到这样的事情:
const myMap = new WeakMap<any-subClass-of-Base, number>([
[A, 1],
[B, 2],
[C, 3]
])
我知道我可以使用更多的泛型关键字,比如:
const myMap = new WeakMap<Function, number>([
[A, 1],
[B, 2],
[C, 3]
])
或仅与任何一种:
const myMap = new WeakMap<any, number>([
[A, 1],
[B, 2],
[C, 3]
])
但两者都完全忽略了这样一个事实,即我预计只能用作继承Base的关键类.