我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。

interface myInterface {
  static Name:string;
}

这可能吗?


当前回答

你可以正常定义接口:

interface MyInterface {
    Name:string;
}

但你不能这么做

class MyClass implements MyInterface {
    static Name:string; // typescript won't care about this field
    Name:string;         // and demand this one instead
}

为了表示一个类应该遵循这个接口来获取它的静态属性,你需要一点技巧:

var MyClass: MyInterface;
MyClass = class {
    static Name:string; // if the class doesn't have that field it won't compile
}

你甚至可以保留类名,TypeScript(2.0)不会介意:

var MyClass: MyInterface;
MyClass = class MyClass {
    static Name:string; // if the class doesn't have that field it won't compile
}

如果你想静态地继承许多接口,你必须首先将它们合并到一个新的接口中:

interface NameInterface {
    Name:string;
}
interface AddressInterface {
    Address:string;
}
interface NameAndAddressInterface extends NameInterface, AddressInterface { }
var MyClass: NameAndAddressInterface;
MyClass = class MyClass {
    static Name:string; // if the class doesn't have that static field code won't compile
    static Address:string; // if the class doesn't have that static field code won't compile
}

或者如果你不想命名合并接口,你可以这样做:

interface NameInterface {
    Name:string;
}
interface AddressInterface {
    Address:string;
}
var MyClass: NameInterface & AddressInterface;
MyClass = class MyClass {
    static Name:string; // if the class doesn't have that static field code won't compile
    static Address:string; // if the class doesn't have that static field code won't compile
}

工作示例

其他回答

温特特拉特给出了一个很好的答案,让我走上了正确的轨道。 然而,强制在静态接口中包含构造函数是非常不方便的。

简化版本

反转extends函数得到:

type Static<TClass extends IStaticInterface & { new(...args) }, IStaticInterface>
  = InstanceType<TClass>;

不需要为接口添加构造函数:

interface IMeow { readonly IsMeow: boolean; }

并像这样方便地使用:

class Cat implements Static<typeof Cat, IMeow> {
  readonly static IsMeow = true;
}

就像之前一样,如果Cat中缺少静态的IsMeow,它会给出一个非常明确的错误。 也像以前一样,它在其他方面仍然正常工作。

奇特的可读性(主观)

在类型后面需要一个"implements"字符串:

type Static<TClass extends IStaticInterface & { new(...args) },
  _txt extends "implements", IStaticInterface>
  = InstanceType<TClass>;

这里再次演示我们的猫:

class Cat implements Static<typeof Cat, "implements", IMeow> {
  static readonly IsMeow = true;
}

合并多个(过多)

这真的不需要,你只需要重复Static<…>,但下面是:

type Static<TClass extends InterfacesCombined & { new(...args) }, _txt extends "implements",
  IStaticInterface, IStatic2 = {}, IStatic3 = {}, IStatic4 = {}, IStatic5 = {},
  InterfacesCombined extends IStaticInterface & IStatic2 & IStatic3 & IStatic4 & IStatic5
    = IStaticInterface & IStatic2 & IStatic3 & IStatic4 & IStatic5>
  = InstanceType<TClass>;

为了演示让我们升级我们的猫更复杂:

interface IPurr { purr(): string; }
interface ILick { Lick(human: any): void; }

用法如下:

class Cat implements IPurr, Static<typeof Cat, "implements", IMeow, ILick> {
  static readonly IsMeow = true;
  static Lick(human: any) { /* obey me homan! */ }
  
  purr() { return "Prrrrr"; }
}

一个具体的静态接口

如果你经常使用静态接口,你不会想要键入所有的静态<…的东西。 首先让我们先把这个小帮手弄走:

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

现在让我们“烘焙”一个静态的ILick接口:

type IStaticLick<TClass extends ILick & New<InstanceType<TClass>> = InstanceType<TClass>;

瞧:

class Cat2 implements IStaticLick<typeof Cat2> {
  static Lick(human: any) { /* obey me homan! */ }
}

到底发生了什么?

我们只是要求typeof T实现一些东西,使其成为“静态接口”的有效参数。

所以如果接口IFoo {stuff} +类Foo实现IFoo说Foo是“stuff”,那么我们所说的是“stuff”必须在T中,因为T被允许在Static<T中,…>。

所以类Foo的implements部分实现了Static<…>并没有真正说明Foo有什么特殊的东西。更确切地说,我们只是说我们有这些花哨的<括号>,里面是一个只接受“东西”滚轮的VIP俱乐部!

换句话说,我们可以写成:

class FakeCat implements IStaticLick<typeof Cat2> { }

...明白我的意思了吧?

我们试图通过要求静态<TClass,…来减少这个明显的问题。>实际实现TClass的实例类型。但是,如果InstanceType<TClass>没有任何实例成员(例如我们的Cat2类),则此方法将不起任何作用。

FakeCat确实实现了Cat2 -因为它不是很难实现:{}。

Demo

操场上的链接

遵循@Duncan的@Bartvds的回答,在这里提供了一个可行的方法。

在Typescript 1.5发布后(@Jun 15 '15),你的有用界面

interface MyType {
    instanceMethod();
}

interface MyTypeStatic {
    new():MyType;
    staticMethod();
}

可以在decorator的帮助下以这种方式实现。

/* class decorator */
function staticImplements<T>() {
    return <U extends T>(constructor: U) => {constructor};
}

@staticImplements<MyTypeStatic>()   /* this statement implements both normal interface & static interface */
class MyTypeClass { /* implements MyType { */ /* so this become optional not required */
    public static staticMethod() {}
    instanceMethod() {}
}

参考我在github issue 13462的评论。

视觉效果: 编译错误,提示缺少静态方法。

静态方法实现后,提示方法缺失。

在静态接口和正常接口完成后进行编译。

虽然静态关键字不支持接口在Typescript 但我们可以通过创建一个具有静态成员的函数接口来实现。

在下面的代码中,我创建了一个函数接口Factory,它有两个静态成员serialNumber和printSerial。

// factory is a function interface
interface Factory<T> {
    (name: string, age: number): T;

    //staic property
    serialNumber: number;

    //static method
    printSrial: () => void;
}

class Dog {
    constructor(public name: string, public age: number) { }
}

const dogFactory: Factory<Dog> = (name, age) => {
    return new Dog(name, age);
}

// initialising static members

dogFactory.serialNumber = 1234;
dogFactory.printSrial = () => console.log(dogFactory.serialNumber);


//instance of Dog that DogFactory creates
const myDog = dogFactory("spike", 3);

//static property that returns 1234
console.log(dogFactory.serialNumber)

//static method that prints the serial 1234
dogFactory.printSrial();

我的解决方案对于添加额外静态构造函数的用例非常有效。我已经测试过了,它通过了所有的测试。如果有人发现有问题,请告诉我。

我做了一个泛型类型,它接受接口和静态接口。

它适用于具体类和抽象类。

我使用条件类型来设计它,这样所有的错误都可以传播 到实现接口的类,而不是接口本身。

注意:错误传播允许vscode快速修复(实现所有方法)。唯一的缺点是你必须自己应用static关键字,因为没有快速修复这个错误的方法。

的接口:

type Class<T = any> = new (...args: any[]) => T;
type AbstractClass<T = any> = abstract new (...args: any[]) => T;

type Interface<C extends Class<InstanceType<C>> | AbstractClass<InstanceType<C>>, SI, I = {}> = 
    C extends Class<InstanceType<C>> 
    // ConcreteClass
    ? InstanceType<C> extends I 
        ? C extends (SI & Class<InstanceType<C>>)
            ? (InstanceType<C> & I)
            : (SI & Class<InstanceType<C>>) // Indicate StaticInterface Error
        : I // Indicate Interface Error
    // AbstractClass
    : InstanceType<C> extends I 
        ? C extends (SI & AbstractClass<InstanceType<C>>)
            ? (InstanceType<C> & I)
            : (SI & AbstractClass<InstanceType<C>>) // Indicate StaticInterface Error
        : I // Indicate Interface Error

用法:

interface MyInterface {
    instanceMethod(): number;
}

interface MyStaticInterface {
    staticMethod(): number;
}
 
class MyClass implements Interface<typeof MyClass, MyStaticInterface, MyInterface> {
    static staticMethod(): number {
        return 50;
    }

    instanceMethod(): number {
        return 100;
    }

    static otherStatic() {
        return "HELLO"
    }

    otherInstance() {
        return "GOODBYE"
    }
}

abstract class MyClass1 implements Interface<typeof MyClass1, MyStaticInterface, MyInterface> {
    static staticMethod(): number {
        return 50;
    }


    instanceMethod(): number {
        return 20;
    }

    static otherStatic() {
        return "HELLO"
    }

    otherInstance() {
        return "GOODBYE"
    }

    abstract abstractMethod() : number;

}

简单的例子

interface Person {
  name: string;
  age: number;
}

abstract class Trackable {
  static TrackInstances: number;
}

class Pablo extends Trackable implements Person {
  constructor(public name: string, public age: number) { Pablo.TrackInstances+=1; }
}
console.log(Pablo.TrackInstances);