简体   繁体   English

接口中的 Typescript static 方法

[英]Typescript static methods in interfaces

I'm looking for a way to require a class to own some static methods without having to implement them by myself (like an interface can define normal methods).我正在寻找一种方法来要求 class 拥有一些 static 方法,而无需自己实现它们(就像接口可以定义普通方法一样)。 Since interfaces do not support static methods, the following code does not work.由于接口不支持 static 方法,因此以下代码不起作用。

interface MyInterface {
  static fromJSON(json: string): MyInterface
  toJSON(): object
}

Abstract classes are not the thing I want, because they do not require the developer to write the method himself, but I have to implement it.抽象类不是我想要的东西,因为它们不需要开发人员自己编写方法,但我必须实现它。
Is there something similar to this, without having to write lots of custom logic?有没有类似的东西,无需编写大量自定义逻辑?

Using the interface from above, the following implementation should not be accepted:使用上面的接口,不应接受以下实现:

class MyClass implements MyInterface {
  // Missing static method "fromJSON"
  toJSON() {
    return {}
  }
}

Neither should this one:这个也不应该:

class MyClass implements MyInterface {
  fromJSON(json: string) {
    return 123 // Wrong type
  }

  toJSON() {
    return {}
  }
}

But this one should be accepted:但是这个应该被接受:

class MyClass implements MyInterface {
  fromJSON(json: string) {
    return new MyClass()
  }

  toJSON() {
    return {}
  }
}

There really isn't much support in TypeScript for constraining the static side of a class. TypeScript 中确实没有太多支持来约束 class 的 static 端。 It's a missing feature;这是一个缺失的功能; see microsoft/TypeScript#14600 for an overall feature request, as well as microsoft/TypeScript#33892 for just the "support static implements on classes" part, and microsoft/TypeScript#34516 for just the "support abstract static class members" part. see microsoft/TypeScript#14600 for an overall feature request, as well as microsoft/TypeScript#33892 for just the "support static implements on classes" part, and microsoft/TypeScript#34516 for just the "support abstract static class members" part.


One big blocker for something like static members of an interface of the form you've shown is that it's hard for the type system to make sense of it in a way that will actually do what you want.对于您所显示的形式的interfacestatic成员之类的东西,一个很大的障碍是类型系统很难以一种实际上会做您想要的方式来理解它。 There's a longstanding open issue, microsoft/TypeScript#3841 , asking that the constructor property of a class should be strongly typed.有一个长期悬而未决的问题, microsoft/TypeScript#3841 ,要求 class 的constructor属性应该是强类型的。 Currently it only has the type Function :目前它只有Function类型:

class Foo {
  instanceProp: string = "i"
  static staticProp: string = "s"
}
const foo = new Foo();
foo.constructor.staticProp; // error!
// -----------> ~~~~~~~~~~ 
// Property 'staticProp' does not exist on type 'Function'

There are some sticky reasons for why this cannot be easily done, spelled out in the issue, but essentially the problem is that subclass constructors are not required to be true subtypes of parent class constructors:有一些棘手的原因说明了为什么这不能轻易完成,但本质上问题是子类构造函数不需要是父 class 构造函数的真正子类型:

class Bar extends Foo {
  subInstanceProp: string;
  constructor(subInstanceProp: string) {
    super();
    this.subInstanceProp = subInstanceProp;
  }
}
const bar = new Bar("hello");

Here, the Bar constructor is of type new (subInstanceProp: string) => Bar , which is not assignable to the type of the Foo constructor, which is new () => Foo .在这里, Bar构造函数的类型是new (subInstanceProp: string) => Bar ,它不能分配给Foo构造函数的类型,即new () => Foo By extends , bar should be assignable to Foo .通过extendsbar应该可以分配给Foo But if bar.constructor is not assignable to Foo['constructor'] , everything breaks.但是如果bar.constructor不能分配给Foo['constructor'] ,那么一切都会中断。

There might be ways around that, but nothing has been implemented so far.可能有办法解决这个问题,但到目前为止还没有实施。

All this means that there's no way to look at an object of type MyInterface and be sure that the thing that constructed it has a fromJSON method.所有这一切意味着没有办法查看 MyInterface 类型的MyInterface并确保构造它的东西具有fromJSON方法。 So having static inside interface definitions doesn't really behave in any useful way.因此,在interface定义中static并没有真正以任何有用的方式表现。


The requests in microsoft/TypeScript#33892 and microsoft/TypeScript#34516, don't have this problem. microsoft/TypeScript#33892 和 microsoft/TypeScript#34516 中的请求没有这个问题。 If you could write this:如果你可以这样写:

class MyClass implements MyInterface static implements MyInterfaceConstructor {
// not valid TS, sorry ------------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  toJSON() { return "" };
  static fromJSON(json: string) { return new MyClass() };
}

or this:或这个:

abstract class MyAbstractClass {
  abstract toJSON(): string;
  abstract static fromJSON(json: string): MyAbstractClass
// ------> ~~~~~~
// not valid TS, sorry
}

you'd have a way to do this.你有办法做到这一点。 Alas, neither of those features have been implemented as of TS4.1, so the only way to proceed is with workarounds.唉,这些功能都没有在 TS4.1 中实现,所以唯一的方法是使用变通方法。


Let's take the MyInterface and MyInterfaceConstructor interfaces I wrote above and see what we can do with them.让我们看看我上面写的MyInterfaceMyInterfaceConstructor接口,看看我们可以用它们做什么。 Right now we can only constrain the instance side via implements MyInterface :现在我们只能通过implements MyInterface来约束实例端:

class MyClass implements MyInterface {
  toJSON() { return "" };
  static fromJSON(json: string) { return new MyClass() };
}

We can't write static implements MyInterfaceConstructor .我们不能写static implements MyInterfaceConstructor But we can make a no-op helper function called staticImplements and call it:但是我们可以创建一个名为staticImplements的无操作助手 function 并将其命名为:

function staticImplements<T>(ctor: T) { }

staticImplements<MyInterfaceConstructor>(MyClass); // okay

The fact that this compiles with no error is your guarantee that MyClass 's static side is acceptable.编译没有错误的事实是您保证MyClass的 static 端是可以接受的。 At runtime this is a no-op, but at compile time this is valuable information.在运行时这是一个空操作,但在编译时这是有价值的信息。 Let's see what happens when we do it wrong:让我们看看当我们做错了会发生什么:

class MyClassBad implements MyInterface {
  toJSON() {
    return ""
  }
}
staticImplements<MyInterfaceConstructor>(MyClassBad); // error!
// ------------------------------------> ~~~~~~~~~~
// Property 'fromJSON' is missing in type 'typeof MyClassBad' 
// but required in type 'MyInterfaceConstructor'.

class MyClassAlsoBad implements MyInterface {
  static fromJSON(json: string) {
    return 123 // Wrong type
  }
  toJSON() {
    return ""
  }
}
staticImplements<MyInterfaceConstructor>(MyClassAlsoBad); // error!
// ------------------------------------> ~~~~~~~~~~~~~~
// The types returned by 'fromJSON(...)' are incompatible between these types.
function validMyClass(ctor: MyInterfaceConstructor) { }

Those are the errors you were looking for.这些是您正在寻找的错误。 Yes, the static constraint and the errors are not located exactly where you want them in the code, but at least you can express this.是的,static 约束和错误并不完全位于代码中您想要的位置,但至少您可以表达这一点。 It's a workaround.这是一种解决方法。

There are other versions of this workaround, possibly using decorators (which are sort of deprecated or on hold until decorator support in JS is finalized), but this is the basic idea: try to assign the constructor type to the "static part" of your interface and see if anything fails.此解决方法还有其他版本,可能使用装饰器(在 JS 中的装饰器支持最终确定之前,这些装饰器已被弃用或保留),但这是基本思想:尝试将构造函数类型分配给您的“静态部分”界面,看看有没有什么问题。

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeScript 继承静态方法强制转换 - TypeScript inheritance static methods cast 静态打字稿类方法树是否可以通过汇总摇动? - Are static typescript class methods tree shakeable by rollup? 从 Typescript 中的实例访问静态方法 - Accessing static methods from instance in Typescript 在 JavaScript/TypeScript 中使用静态引用继承实例方法 - Inheriting Instance Methods with Static References in JavaScript/TypeScript 在 typescript 中使用另一个 class 中的 static class 方法 - using static class methods in another class in typescript 有没有办法在 Typescript 或 ES6 中查看类的所有静态变量和方法? - Is there a way to see all static variables and methods of a class in Typescript or ES6? TypeScript - 键入一个返回绑定到类的静态方法的函数 - TypeScript - typing a function that returns static methods bound to a class 在JavaScript / TypeScript中,带有“方法可能是静态”警告的方法是否被视为不良形式? - Are methods with a “method could be static” warning considered bad form in JavaScript/TypeScript? TypeScript:访问类中的静态方法(相同的或不同的) - TypeScript: Access static methods within classes (the same or another ones) 在 Typescript 中访问对象的类的 static 方法? - Access a object's class's static methods in Typescript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM