如何在TypeScript界面中定义静态属性

How to define static property in TypeScript interface

我只想在Typescript接口中声明静态属性? 我没有找到关于此的任何地方。

1
2
3
interface myInterface {
  static Name:string;
}

可能吗?


遵循@Duncan的@Bartvds的答案,这里提供了一种经过多年的可行方法。

在Typescript 1.5发布之后(@Jun 15 '15),这是您的有用界面

1
2
3
4
5
6
7
8
interface MyType {
    instanceMethod();
}

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

可以在装饰器的帮助下以这种方式实现。

1
2
3
4
5
6
7
8
9
10
/* 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开放问题13462上的评论。

视觉效果:
缺少静态方法提示的编译错误。
enter image description here

实施静态方法后,提示缺少方法。
enter image description here

静态接口和普通接口都满足后,编译通过。
enter image description here


您无法在TypeScript中的接口上定义静态属性。

假设您要更改Date对象,而不是尝试添加到Date的定义中,则可以将其包装,或者简单地创建富日期类来执行Date不能做的事情。

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

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

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

1
2
3
4
5
interface Date {
    MinValue: Date;
}

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

调用使用:

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

而且,如果您想在没有实例的情况下使它可用,您也可以...但是有点麻烦。

1
2
3
4
5
interface DateStatic extends Date {
    MinValue: Date;
}

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

调用使用:

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


您可以正常定义接口:

1
2
3
interface MyInterface {
    Name:string;
}

但是你不能只是做

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

为了表示一个类应该遵循此接口的静态属性,您需要一些技巧:

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

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

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

如果您不想从多个接口静态继承,则必须先将它们合并为一个新接口:

1
2
3
4
5
6
7
8
9
10
11
12
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
}

或者,如果您不想命名合并接口,则可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
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
}

工作实例


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

如果您使用TypeScript编写类,那么给出的先前答案当然是正确的。它可能会帮助其他人知道,如果您描述的是已在其他地方实现的对象,则可以像这样声明包含静态属性的全局构造函数:

1
2
3
4
declare var myInterface : {
  new(): Interface;
  Name:string;
}


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

1
2
3
4
5
6
7
8
interface MyType {
    instanceMethod();
}

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


如果要定义一个静态类(即所有方法/属性都是静态的),则可以执行以下操作:

1
2
3
4
5
6
7
8
9
interface MyStaticClassInterface {
  foo():string;
}

var myStaticClass:MyStaticClassInterface = {
  foo() {
    return 'bar';
  }
};

在这种情况下,静态"类"实际上只是一个普通的ol-js对象,它实现了MyStaticClassInterface的所有方法


静态修饰符不能出现在类型成员上(TypeScript错误TS1070)。这就是为什么我建议使用抽象类来解决任务的原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Interface definition
abstract class MyInterface {
  static MyName: string;
  abstract getText(): string;
}

// Interface implementation
class MyClass extends MyInterface {
  static MyName = 'TestName';
  getText(): string {
    return `This is my name static name"${MyClass.MyName}".`;
  }
}

// Test run
const test: MyInterface = new MyClass();
console.log(test.getText());

我找到了一种针对我的特定用例的方法(没有装饰器)。

检查静态成员的重要部分是IObjectClass并在createObject方法中使用cls: IObjectClass< T >

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//------------------------
// Library
//------------------------
interface IObject {
  id: number;
}
interface IObjectClass< T > {
  new(): T;
  table_name: string;
}
function createObject<T extends IObject>(cls: IObjectClass< T >, data:Partial< T >):T {
  let obj:T = (Object).assign({},
    data,
    {
      id: 1,
      table_name: cls.table_name,
    }
  )
  return obj;
}

//------------------------
// Implementation
//------------------------
export class User implements IObject {
  static table_name: string = 'user';
  id: number;
  name: string;
}

//------------------------
// Application
//------------------------
let user = createObject(User, {name: 'Jimmy'});
console.log(user.name);

您可以使用相同的名称将接口与名称空间合并:

1
2
3
4
5
interface myInterface { }

namespace myInterface {
  Name:string;
}

但是此接口仅在知道其具有属性Name时才有用。您无法实现它。


对的,这是可能的。这是解决方案

1
2
3
4
5
6
7
8
9
10
11
12
export interface Foo {

    test(): void;
}

export namespace Foo {

    export function statMethod(): void {
        console.log(2);
    }

}


虽然Typescript的界面不支持static关键字
但是我们可以通过创建具有静态成员的function interface来实现。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 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();