gpt4 book ai didi

typescript - 将 InstanceType 与工厂函数一起使用

转载 作者:行者123 更新时间:2023-12-02 03:07:33 26 4
gpt4 key购买 nike

我有一个相当简单的工厂函数,它使用构造函数映射来根据传入的字符串参数确定要创建的正确对象类型。

我知道示例中描述的将类构造函数传递给工厂的工厂模式,但在我的例子中,我需要传递一个简单的字符串。

class Vehicle {
public wheels: number;
}
class Car extends Vehicle {
public drive: number
}
class Bike extends Vehicle {
public ride: number;
}

const CTORS = {
car: Car,
bike: Bike
}

type VehicleTypes = typeof CTORS;

function factory<T extends keyof VehicleTypes>(name: T): InstanceType<VehicleTypes[T]> {
let ctor: VehicleTypes[T] = CTORS[name];

// un-comment to see error
// return new ctor();

return new ctor() as InstanceType<VehicleTypes[T]>;
}

let abc = factory('bike');
abc.ride = 5; // type checks ok

上面的工作和类型检查没问题,但是为了避免编译器错误,返回上的显式类型是必要的:

(Type 'Car | Bike' is not assignable to type 'InstanceType<{ car: typeof Car; bike: typeof Bike; }[T]>'.  Type 'Car' is not assignable to type 'InstanceType<{ car: typeof Car; bike: typeof Bike; }[T])

我怀疑 typescript 提示返回值不是所有潜在实例的联合。但是我无法弄清楚如何应用这些类型,以至于不需要显式键入覆盖。我也尝试了以下也无济于事:

type ReturnTypes = { 
[P in keyof VehicleTypes]: InstanceType<VehicleTypes[P]>
}
function factory<T extends keyof VehicleTypes>(name: T): ReturnTypes[T] {
let ctor = CTORS[name];
return new ctor();
}

最佳答案

这是目前 TypeScript 的一个限制:未解析的条件类型,意味着那些依赖于尚未指定的通用类型参数的类型,对编译器是不透明的;它真的看不到可以分配给它的某些值。类型InstanceType<T>defined像这样:

type InstanceType<T extends new (...args: any) => any> = 
T extends new (...args: any) => infer R ? R : any;

这是一个条件类型, factory() 的实现中, 类型 InstanceType<VehicleTypes[T]>未解决,因为T未指定。


有几个开放的 GitHub 问题,其中包含使此类 Unresolved 条件类型更易于处理的建议,但目前都没有实现(截至 TS3.7)。如果您足够关心去那里给他们一个 👍 或以其他方式为他们提倡,这里有一些指向他们的链接:


现在,我会说要么像您一样使用类型断言,要么找到一种不依赖于条件类型的方式来表示您的类型。一种可能的方法是注意 TypeScript 中的类构造函数被赋予 prototype。与其实例类型相同类型的属性。这有点奇怪而且不太正确,因为实际原型(prototype)不会有任何仅实例属性,但是 that's the way it is and it's unlikely to change .

所以,你可以自己制作InstanceType使用这个事实:

type MyInstanceType<T extends { prototype: any }> = T['prototype'];

然后你就可以写了

function factory<T extends keyof VehicleTypes>(name: T): MyInstanceType<VehicleTypes[T]> {
let ctor: VehicleTypes[T] = CTORS[name];
return new ctor();
}

没有错误,你仍然得到你期望的类型检查:

let abc = factory('bike');
abc.ride = 5; // type checks ok

希望对您有所帮助;祝你好运!

Link to code

关于typescript - 将 InstanceType<T> 与工厂函数一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58559221/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com