您当然可以描述并声明一个以这种方式工作的类构造函数:
interface CarConstructor {
new <T>(): Car<T | undefined>;
new <T>(maxSpeed: T): Car<T>;
}
interface Car<T> {
maxSpeed: T
}
declare const Car: CarConstructor;
const car1 = new Car<number>(1);
car1.maxSpeed // maxSpeed is of type number
const car2 = new Car<number>();
car2.maxSpeed // maxSpeed is of type number | undefined
CarConstructor 有两个构造签名,按照您所说的方式重载。
问题在于实现这样的CarConstructor。 TypeScript 不允许您将类型参数放在 class 构造函数上,因为目前编译器从类声明本身而不是从构造函数获取任何泛型类类型参数:
class BadCar<T> {
maxSpeed: T;
constructor<T>(): Car<T | undefined>; // error! no type params
constructor<T>(maxSpeed: T): Car<T>; // error! no type params
constructor(maxSpeed?: T) {
this.maxSpeed = maxSpeed; // error! can't tell this is valid
}
}
现在你所能做的就是创建一个“足够接近”的类,然后注释或assert 它是CarConstructor:
const Car: CarConstructor = class <T> {
maxSpeed: T;
constructor(maxSpeed?: T) {
this.maxSpeed = maxSpeed as T; // <-- assume undefined is in T
}
}
这可行,但它很麻烦,并且可能会变得更麻烦,因为Car 中存在的功能越多(你会发现自己到处都在做冗余的属性/方法定义)。
存在一个现有的 GitHub 问题,microsoft/TypeScript#35387,要求更容易直接实现具有此类重载构造函数的类。如果你真的需要这个,你可能想去那个问题,给它一个 ? 并描述为什么你的用例是引人注目的。
当然,最简单的事情就是不要与 TypeScript 对抗,而是使用不同的解决方案,比如工厂函数:
class DumbCar<T> {
constructor(public maxSpeed: T) { }
}
function newCar<T>(x: T): Car<T>;
function newCar<T>(): Car<T | undefined>;
function newCar<T>(x?: T): Car<T | undefined> | Car<T> {
return new DumbCar(x);
}
Playground link to code