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

interface myInterface {
  static Name:string;
}

这可能吗?


当前回答

在TypeScript中,你不能在接口上定义静态属性。

假设您想要更改Date对象,而不是尝试添加到Date的定义中,您可以包装它,或者简单地创建富Date类来完成Date没有完成的工作。

class RichDate {
    public static MinValue = new Date();
}

因为Date是TypeScript中的一个接口,你不能使用extends关键字将它扩展为一个类,这有点遗憾,因为如果Date是一个类,这将是一个很好的解决方案。

如果你想扩展Date对象以在原型上提供MinValue属性,你可以:

interface Date {
    MinValue: Date;
}

Date.prototype.MinValue = new Date(0);

使用:

var x = new Date();
console.log(x.MinValue);

如果你想让它在没有实例的情况下可用,你也可以…但这有点繁琐。

interface DateStatic extends Date {
    MinValue: Date;
}

Date['MinValue'] = new Date(0);

使用:

var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);

其他回答

这里有一个相当简单的方法:

interface MyClass {
    new (): MyClassInstance;
    staticMethod(): string;
}

interface MyClassInstance {
    instanceMethod(): string;
}

const Class: MyClass = class {
    static staticMethod() {
        return "This is a static method";
    }
    instanceMethod() {
        return "This is an instance method";
    }
}

Class.staticMethod();

// Has type MyClassInstance
const instance = new Class();
instance.instanceMethod();

请注意,这并不允许您像通常那样让类扩展接口,但对于许多情况来说,这已经足够好了。

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

简化版本

反转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

操场上的链接

简单的例子

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);

@duncan上面的解决方案为静态类型指定new()也适用于接口:

interface MyType {
    instanceMethod();
}

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

静态属性通常放在对象的(全局)构造函数上,而“interface”关键字适用于对象的实例。

如果你用TypeScript编写类,前面给出的答案当然是正确的。如果你描述的是一个已经在其他地方实现的对象,那么包含静态属性的全局构造函数可以这样声明:

declare var myInterface : {
  new(): Interface;
  Name:string;
}