【问题标题】:Typescript function to generate a class implementing an interface用于生成实现接口的类的 Typescript 函数
【发布时间】:2023-03-31 14:34:01
【问题描述】:

我的问题是关于打字稿机制中我不理解的一点:为什么在下面的代码中,ComposerA 是正确的而 ComposerB 不是?

type Ctor<T = {}> = new (...args: any[]) => T;

function ComposerA<T extends Ctor>(Target: T) {
  return class extends Target {
    ...
  }
}

function ComposerB<T extends Ctor>(Target: T) {
  return class implements Target {
    ...
  }
}

在 ComposerB 中我得到错误 -> 'Target' 指的是一个值,但在这里被用作一种类型。

我认为有一个我不明白的概念。是否有可能实现一个接受一个对象并实现它的功能。我需要实现而不是扩展,这个例子是我原始代码的简化,我已经扩展了另一个类。

【问题讨论】:

  • 你想如何实现对象? (实例),你应该在你的案例类型 T 中实现类型?
  • 接口不是对象,接口在运行时不存在,因此ComposerB 无法接收接口作为其参数的值。这就是错误消息所说的。 Target,在这两个函数中,是一个在运行时存在的值,但 implements 期望一个类型,而不是一个值。那么,你能解释一下你所说的“接受一个对象并实现它的函数”是什么意思吗?
  • 事实上,我不想从一个类而不是一个接口来实现,并从生成的类中的类中复制原型。我不想在我的函数中扩展两个类,合并两个类的原型:基类和目标类。添加工具会在 typescript 中提供对象之后将使用的接口。我不知道这是否是最好的解决方案。好像不是这样的。
  • TypeScript 类型是structural,从类用户的角度来看,class implements SomeInterface { ... }class { ... } 没有什么不同,前提是实现确实符合接口。 implements 仅用于确保类实现确实符合接口,并且为了做到这一点,有一些限制 - 引用另一条错误消息,“一个类只能实现一个对象类型或对象类型的交集具有静态已知的成员。”
  • " 在我的函数中扩展两个类,合并两个类的原型" - 如果我理解正确,您想要 extend 基类(在您的示例中不存在),并从 @ 添加方法987654330@ 类 - 那么implements 没有帮助,您需要自己组合原型,就像在 javascript 中一样,因为 TypeScript 只是对代码进行类型检查,它不会为您做任何类型操作.

标签: typescript inheritance interface


【解决方案1】:

你不能在运行时implement 任何东西,但你可以向类的原型添加方法并使用泛型更改构造函数签名:

type Class<T={}> = new (...args: any) => T;

interface Fooable {
    foo(n: number):string
}

function withFoo<T>(k: Class<T>): Class<T & Fooable> {

    k.prototype.foo = function(n: number): string {
        return "foo";
    }

    return k as Class<T & Fooable>;
}

class Blah {
    blah(s: string) {}    
}

let BlahFooable = withFoo(Blah);

let b = new BlahFooable;

b.blah("hey") // ok
b.foo(42) // ok

Play

以更通用的方式:

type Class<T={}> = new (...args: any) => T;

function Mixin<T, M extends object>(cls: Class<T>, mixin: M): Class<T & M> {
    Object.assign(cls.prototype, mixin);
    return cls as Class<T & M>;
} 

class Blah {
    blah(s: string) {}
}

let BlahWithFoo = Mixin(Blah, {
    foo(n: number): string {
        return "foo";
    }
});

let b = new BlahWithFoo();

b.blah("hey") // ok
b.foo(42) // ok

【讨论】:

    猜你喜欢
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2021-07-20
    • 2016-09-03
    相关资源
    最近更新 更多