为什么打字稿混合需要一个带有单个rest参数的构造函数any []?

凯夫塞特勒

我正在将功能混合项目从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
}   
hackape

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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类常见问题

为什么打字稿混合需要一个带有单个rest参数的构造函数any []?

来自分类Dev

我可以有一个带有输入参数指南的打字稿类构造函数吗?

来自分类Dev

为什么在Java 16中IndexOutOfBoundsException现在有一个带有长索引的构造函数作为参数?

来自分类Dev

为什么我的Arduino类构造函数需要一个参数?

来自分类Dev

C ++:没有匹配的调用函数:为什么需要一个空的构造函数?

来自分类Dev

为什么我们只有一个带有@Inject批注的构造函数?

来自分类Dev

打字稿-在函数的参数中添加一个参数

来自分类Dev

构造一个带有无限参数的函数

来自分类Dev

为什么编译器需要复制构造函数,需要并拥有一个移动构造函数,却不使用其中任何一个?

来自分类Dev

为什么一个元组在`[Serializable]`时没有无参数的构造函数?

来自分类Dev

为什么没有为方法/构造函数的第一个参数命名?

来自分类Dev

为什么没有为方法/构造函数的第一个参数命名?

来自分类Dev

为什么一个元组在`[Serializable]`时没有无参数构造函数?

来自分类Dev

为什么默认构造函数和参数化构造函数都在一个类中?

来自分类Dev

这样绑定一个参数,并带有一个新的构造函数?

来自分类Dev

打字稿:需要另一个参数时需要参数

来自分类Dev

如何在打字稿中将参数从一个具有可变参数的函数传递到另一个具有可变参数的函数?

来自分类Dev

打字稿:隐式调用带有注入参数的构造函数

来自分类Dev

重载的构造函数,一个带有两个参数,一个没有参数

来自分类Dev

我想我需要一个带有构造函数的静态类?

来自分类Dev

为什么在这个Java通用子类中需要一个构造函数?

来自分类Dev

为什么`std :: pair <int,movable>`需要一个[deleted]`const&`复制构造函数?

来自分类Dev

为什么我需要在这里显式编写一个构造函数?

来自分类Dev

为什么我们需要一个用户提供的const对象构造函数?

来自分类Dev

为什么模型绑定器需要一个空的构造函数

来自分类Dev

为什么在扩展的抽象类中需要另一个构造函数?

来自分类Dev

为什么我需要在这里显式编写一个构造函数?

来自分类Dev

为什么第一个参数是User类型,为什么不是string?打字稿谁能解释我为什么

来自分类Dev

C ++中带有另一个模板类作为参数的构造函数

Related 相关文章

  1. 1

    为什么打字稿混合需要一个带有单个rest参数的构造函数any []?

  2. 2

    我可以有一个带有输入参数指南的打字稿类构造函数吗?

  3. 3

    为什么在Java 16中IndexOutOfBoundsException现在有一个带有长索引的构造函数作为参数?

  4. 4

    为什么我的Arduino类构造函数需要一个参数?

  5. 5

    C ++:没有匹配的调用函数:为什么需要一个空的构造函数?

  6. 6

    为什么我们只有一个带有@Inject批注的构造函数?

  7. 7

    打字稿-在函数的参数中添加一个参数

  8. 8

    构造一个带有无限参数的函数

  9. 9

    为什么编译器需要复制构造函数,需要并拥有一个移动构造函数,却不使用其中任何一个?

  10. 10

    为什么一个元组在`[Serializable]`时没有无参数的构造函数?

  11. 11

    为什么没有为方法/构造函数的第一个参数命名?

  12. 12

    为什么没有为方法/构造函数的第一个参数命名?

  13. 13

    为什么一个元组在`[Serializable]`时没有无参数构造函数?

  14. 14

    为什么默认构造函数和参数化构造函数都在一个类中?

  15. 15

    这样绑定一个参数,并带有一个新的构造函数?

  16. 16

    打字稿:需要另一个参数时需要参数

  17. 17

    如何在打字稿中将参数从一个具有可变参数的函数传递到另一个具有可变参数的函数?

  18. 18

    打字稿:隐式调用带有注入参数的构造函数

  19. 19

    重载的构造函数,一个带有两个参数,一个没有参数

  20. 20

    我想我需要一个带有构造函数的静态类?

  21. 21

    为什么在这个Java通用子类中需要一个构造函数?

  22. 22

    为什么`std :: pair <int,movable>`需要一个[deleted]`const&`复制构造函数?

  23. 23

    为什么我需要在这里显式编写一个构造函数?

  24. 24

    为什么我们需要一个用户提供的const对象构造函数?

  25. 25

    为什么模型绑定器需要一个空的构造函数

  26. 26

    为什么在扩展的抽象类中需要另一个构造函数?

  27. 27

    为什么我需要在这里显式编写一个构造函数?

  28. 28

    为什么第一个参数是User类型,为什么不是string?打字稿谁能解释我为什么

  29. 29

    C ++中带有另一个模板类作为参数的构造函数

热门标签

归档