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

interface myInterface {
  static Name:string;
}

这可能吗?


当前回答

虽然静态关键字不支持接口在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();

其他回答

我为我的特定用例找到了这样做的方法(不需要装饰器)。

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

//------------------------
// 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 = (<any>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);

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

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

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

解决方案

返回I的实例类型,并确保C扩展I:

type StaticImplements<I extends new (...args: any[]) => any, C extends I> = InstanceType<I>;

实例方法接口:

interface MyInstance {
    instanceMethod();
}

接口采用静态方法:

interface MyClassStatic {
    new (...args: any[]): MyInstance;
    staticMethod();
}

类需要静态方法并使用自己的方法进行扩展:

class MyClass implements StaticImplements<MyClassStatic, typeof MyClass> {
    static staticMethod();
    static ownStaticMethod();
    instanceMethod();
    ownInstanceMethod();
}

推理

在接口中定义静态方法将在#33892中讨论,抽象静态方法将在#34516中讨论。

基于Val和Aleksey的回答(谢谢),这个解决方案:

不需要额外的运行时值 保留类自身的成员信息 允许构造函数约束

Test

原样-游乐场连结:

MyClass.staticMethod(); // OK
MyClass.ownStaticMethod(); // OK
new MyClass().instanceMethod(); // OK
new MyClass().ownInstanceMethod(); // OK

如果从MyClass - Playground中删除staticMethod:

class MyClass implements StaticImplements<MyClassStatic, typeof MyClass> {} // Type 'typeof MyClass' does not satisfy the constraint 'MyClassStatic'. Property 'staticMethod' is missing in type 'typeof MyClass' but required in type 'MyClassStatic'.

如果从MyClass - Playground中删除instanceMethod:

class MyClass implements StaticImplements<MyClassStatic, typeof MyClass> {} // Class 'MyClass' incorrectly implements interface 'MyInstance'. Property 'instanceMethod' is missing in type 'MyClass' but required in type 'MyInstance'.

你可以正常定义接口:

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
}

工作示例

这里没有提到的另一个选项是用表示静态接口的类型定义变量,并为其分配类表达式:

interface MyType {
    instanceMethod(): void;
}

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

// ok
const MyTypeClass: MyTypeStatic = class MyTypeClass {
    public static staticMethod() { }
    instanceMethod() { }
}

// error: 'instanceMethod' is missing
const MyTypeClass1: MyTypeStatic = class MyTypeClass {
    public static staticMethod() { }
}

// error: 'staticMethod' is missing
const MyTypeClass2: MyTypeStatic = class MyTypeClass {
    instanceMethod() { }
}

效果与使用装饰器的应答相同,但没有装饰器的开销

操场上

GitHub上的相关建议/讨论