带有约束的通用工厂功能和TS2322的默认参数错误

时间:2019-05-06 12:32:01

标签: typescript

我有某种基类...

class BaseClass<ItemType> {
    // Irrelevant parameters elided for simplicity...
    constructor(__items: Iterable<ItemType>) {}
}

我想要一个工厂,该工厂可以返回该类或某个子类的实例,该工厂将提供消除参数的某些值。调用者可以提供要使用这些参数构造的子类的构造函数,因此让我们声明一个接口...

export interface GenericConstructorInterface<S, T extends BaseClass<S>> {
    new(items: Iterable<S>): T;
}

现在我们可以声明工厂了...

// This works...
export function factory<A, B extends BaseClass<A>>(__items: Iterable<A>, subclassConstructor: GenericConstructorInterface<A, B>): B {
    return new subclassConstructor(__items);
}

但是,我不想谴责所有调用者必须提供构造函数,所以我尝试

// The default parameter won't typecheck:
// Type 'typeof BaseClass' is not assignable to type 'GenericConstructorInterface<A, B>'.
// Type 'BaseClass<A>' is not assignable to type 'B'.ts(2322)
export function factory<A, B extends BaseClass<A>>(__items: Iterable<A>, subclassConstructor: GenericConstructorInterface<A, B> = BaseClass): B {
    return new subclassConstructor(__items);
}

,现在默认参数不会进行类型检查。我在这里误解了什么?

1 个答案:

答案 0 :(得分:1)

任何默认参数都必须与所有可能的类型参数兼容。由于subclassConstructor依赖于B,因此对于任何传入的BaseClass,类B都不是默认值。(B可以是{{1 }},因此DerivedFromBaseClass将不是BaseClass的有效默认值。

您可以在默认参数值中使用类型断言,尽管更好的选择是使用多个重载。像这样,呼叫者无法传递与默认设置不一致的subclassConstructor

B