我正在将功能混合项目从javascript迁移到打字稿。我所有的JavaScript minxins都有一个带有单个参数的构造函数签名constructor(props){}
。
在打字稿中,我根据https://www.typescriptlang.org/docs/handbook/mixins.html上的官方文档定义了mixin构造函数类型:
export type ConstrainedMixin<T = {}> = new (...args: any[]) => T;
即使我将mixin签名更改为:
export type ConstrainedMixin<T = {}> = new (props: any) => T;
并更新实现,TSC将抛出错误:
TS2545:mixin类必须具有一个带有单个类型为'any []'的rest参数的构造函数。
这很不幸,因为它无法为传递给构造函数的参数创建唯一的类型签名。现在,我还需要迁移所有现有的构造函数。如何为mixin构造函数创建更明确的类型接口?
我创建了一个游乐场示例
您可以在此屏幕快照中看到MIXIN定义上的编译器错误,并指出mixin类必须具有单个rest参数。即使类型定义是:
type ConstrainedMixin<T = {}> = new (props: any) => T;
在示例中,const mg = new MixedGeneric({cool: 'bro'});
我想为该{cool: 'bro'}
对象创建一个接口,并从mixin定义中强制实施。我不确定如何正确执行此操作。...args: any[]
Update sounds like this may be some anti pattern so here is further explanation. I am building an entity component system. In my current implementation I have chains of mixins like:
const MixedEntity = RenderMixin(PhysicsMixin(GeometryMixin(Entity));
const entityInstance = new MixedEntity({bunch: "of", props: "that mixins use"});
When the final MixedEntity is instantiated it is passed a props
data bag object. All the Mixins have their own initialization logic in their constructors that looks for specific properties on the props
object.
where my previous mixin classes had constructors like:
constructor(props){
super(props);
if(props.Thing) // do props.thing
}
I now have to migrate the constructors to :
constructor(...args: any[]){
const props = args[0]
super(props);
if(props.Thing) // do props thing
}
Mixin pattern in TS is meant to extend the base class with extra methods or properties, but not to tamper the constructor signature. So the derived class is supposed to keep its constructor signature identical to the base class it extends.
这个A mixin class must have a constructor with a single rest parameter of type 'any[]'
限制问题TS背后的理由并不在乎,它只会将结构传递给super(…args)
它并让它完成工作。
因此,如果要约束构造函数参数,只需在基类构造函数签名中进行即可。
type Constructor = new (...args: any[]) => {};
function MixinGeneric<TBase extends Constructor>(Base: TBase) {
return class extends Base {
// …mixin traits
}
}
class Generic {
// ctor param constraint goes here:
constructor<P extends { cool: string }>(props: P) {}
}
// and it’ll check:
const mg = new MixedGeneric({cool: 'bro'});
更新以响应OP的更新
是的,篡改构造函数签名被认为是反模式。但是编码人员一直都在违反规则。只要您了解自己在做什么,就一定要有创造力。
在操场上检查一下。
诀窍是通过使用类型断言和实用程序类型束来绕过TS限制。
// Utility types:
type GetProps<TBase> = TBase extends new (props: infer P) => any ? P : never
type GetInstance<TBase> = TBase extends new (...args: any[]) => infer I ? I : never
type MergeCtor<A, B> = new (props: GetProps<A> & GetProps<B>) => GetInstance<A> & GetInstance<B>
// Usage:
// bypass the restriction and manually type the signature
function GeometryMixin<TBase extends MixinBase>(Base: TBase) {
// key 1: assert Base as any to mute the TS error
const Derived = class Geometry extends (Base as any) {
shape: 'rectangle' | 'triangle'
constructor(props: { shape: 'rectangle' | 'triangle' }) {
super(props)
this.shape = props.shape
}
}
// key 2: manually cast type to be MergeCtor
return Derived as MergeCtor<typeof Derived, TBase>
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句