【问题标题】:Restrict type by super class in interface通过接口中的超类限制类型
【发布时间】:2018-02-01 20:31:50
【问题描述】:

我想创建一个接口,它定义了一组键值对,其中值限制为 typeof classWhichExtendsSpecificSuperClass。

比如这个界面:

interface MyInterface {
     key: typeof SuperClass
}

还有这个基类:

class BaseClass extends SuperClass {...}

以这种方式应用:

function myFunction(arg: MyInterface) {...};

myFunction({
   key: BaseClass
});

上面的代码会告诉我 typeof BaseClass 不能分配给 typeof SuperClass。

现在我知道我正在做的事情是不正确的,但还有其他可能吗?我想确保“key”的唯一允许值是扩展 SuperClass 的 typeof 类?

如果我在处理函数,我可以使用泛型,但据我所知,没有办法在对象属性上表达泛型。

任何帮助都会很棒!

【问题讨论】:

  • 不确定是什么问题,下面的代码对我有用 class SuperClass { nr: number; } interface MyInterface { key: typeof SuperClass } class BaseClass 扩展 SuperClass { s: string; } function myFunction(arg: MyInterface) { var c = new arg.key(); } myFunction({ key: BaseClass });
  • 您使用的是什么版本的打字稿?我进行了此编译并退出了该项目,现在它似乎有问题。
  • 我使用的是 2.4.2

标签: typescript inheritance interface typeof


【解决方案1】:

如果扩展SuperClass 的所有类都具有兼容的构造函数参数,那么您的代码应该可以正常工作。例如:

class SuperClass {
  superValue: string;
}
interface MyInterface {
     key: typeof SuperClass
}
class BaseClass extends SuperClass {
  baseValue: string;
}
function myFunction(arg: MyInterface) { };
myFunction({
   key: BaseClass // no error
});

这里没有问题,因为BaseClassSuperClass 都可以用零参数构造。但是如果你改变BaseClass的构造函数:

class BaseClass extends SuperClass {
  baseValue: string;
  constructor(someArgument: string) {
    super();
  }
}

当你调用myFunction()时你会得到你提到的错误:

类型参数'{ key: typeof BaseClass; }' 不可分配给“MyInterface”类型的参数。 属性“键”的类型不兼容。 类型“typeof BaseClass”不可分配给类型“typeof SuperClass”。

现在,根据您要对MyInterface 执行的操作,该错误可能很重要。您是否打算获取MyInterface 值的key 属性并使用它来构造SuperClass 的某个子类的实例?例如:

declare let myInterface: MyInterface;
let someInstance = new myInterface.key();

如果是这样,那么您需要确保类构造函数接受正确数量和类型的参数,并且该错误对您有所帮助。它告诉您将BaseClass 构造函数更改为与SuperClass 的构造函数兼容。例如,如果我们将someArgument 设为可选:

class BaseClass extends SuperClass {
  baseValue: string;
  constructor(someArgument?: string) {
    super();
  }
}

然后错误就消失了,因为 new SubClass() 现在可以在没有参数的情况下工作。


如果您打算使用MyInterface 来构造实例,并且关心构造函数采用的参数的数量和类型,并且您只是希望它出于某种原因持有 some 类构造函数...然后您可以这样做:

type Constructor<T> = {
  new(...args: any[]): T; // any number and type of arguments
}
interface MyInterface {
     key: Constructor<SuperClass>
}

即使构造函数签名不兼容,现在myFunction() 也可以工作。那是因为你真的不想把自己限制在typeof SuperClass;您愿意接受创建SuperClass任何 构造函数,这就是Constructor&lt;SuperClass&gt; 的含义。所以错误消失了,你很高兴。


希望这两种解决方案中的一种对您有用。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2018-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-09
    • 1970-01-01
    相关资源
    最近更新 更多