Проблема в том, что общий параметр T
в Bar<T>
, кажется, применяется только к части экземпляра Bar
, а не к статической части, хотя T
используется в сигнатуре конструктора (а конструктор принадлежитстатическая часть).
Обходной путь должен иметь явный интерфейс, который определяет статическую часть, , как предлагается в этом ответе , и использовать функцию "высшего порядка" Bar<T>()
вместо класса:
function create<T extends new(...args: any[]) => any>(
cls: T, ...args: ConstructorParameters<T>): InstanceType<T> {
return new cls(...args);
}
interface BarConstructor<T, C> {
new(a: T, b: string): C;
}
class BarImpl<T> {
constructor(a: T, b: string) {}
}
function Bar<T>(): BarConstructor<T, BarImpl<T>> {
return BarImpl;
}
let b = create(Bar(), "asdf", "a"); // OK because Bar() by itself implies Bar<{}>(),
// and "asdf" is assignable to {}
// you can turn it into an error by having `never` as default for T like this
// function Bar<T = never>()
let c = create(Bar<number>(), "asdf", "a"); // error as expected
let d = create(Bar<number>(), 20, "a"); // OK