Подтвердить что ты не робот

Как определить статическое свойство в интерфейсе TypeScript

Я просто хочу объявить статическое свойство в интерфейсе typescript? Я ничего не нашел по этому поводу.

interface myInterface {
  static Name:string;
}

Возможно ли это?

4b9b3361

Ответ 1

Вы не можете определить статическое свойство на интерфейсе в TypeScript.

Предположим, вы хотели изменить объект Date, вместо того, чтобы пытаться добавить определения Date, вы можете его обернуть или просто создать свой богатый класс даты, чтобы сделать материал, который Date не сделать.

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

Поскольку Date является интерфейсом в TypeScript, вы не можете расширять его классом с помощью ключевого слова extends, что немного позорно, поскольку это было бы хорошим решением, если дата была классом.

Если вы хотите расширить объект 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);

Ответ 2

Следуйте @Duncan @Bartvds answer здесь, чтобы обеспечить работоспособный путь спустя годы.

На этом этапе после выпуска Typescript 1.5 (@Jun 15 '15) ваш полезный интерфейс

interface MyType {
    instanceMethod();
}

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

может быть реализован таким образом с помощью декоратора.

/* 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

Ответ 3

Статические свойства обычно помещаются в (глобальный) конструктор для объекта, тогда как ключевое слово "interface" применяется к экземплярам объекта.

Предыдущий ответ, конечно, правильный, если вы пишете класс в TypeScript. Это может помочь другим узнать, что если вы описываете объект, который уже реализован в другом месте, глобальный конструктор, включающий статические свойства, может быть объявлен следующим образом:

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

Ответ 4

Вы можете определить интерфейс как обычно:

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
}

Рабочий пример

Ответ 5

@duncan решение выше, указав new() для статического типа, также работает с интерфейсами:

interface MyType {
    instanceMethod();
}

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

Ответ 6

Если вы хотите определить статический класс (т.е. все методы/свойства являются статическими), вы можете сделать что-то вроде этого:

interface MyStaticClassInterface {
  foo():string;
}

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

В этом случае статический "класс" на самом деле представляет собой просто простой-ol'-js-объект, который реализует все методы MyStaticClassInterface

Ответ 7

Вы можете объединить интерфейс с пространством имен с тем же именем:

interface myInterface { }

namespace myInterface {
  Name:string;
}

Но этот интерфейс полезен только для того, чтобы знать, что у него есть свойство Name. Вы не можете его реализовать.

Ответ 8

Я нашел способ сделать это (без декораторов) для моего конкретного случая использования.

Важной частью, которая проверяет статические элементы, является IObjectClass и используя cls: IObjectClass<T> в методе createObject:

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

Ответ 9

AFAIK, это невозможно.

К сожалению, это не старая добрая Java.

Ответ 10

Да, это возможно. Вот решение

export interface Foo {

    test(): void;
}

export namespace Foo {

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

}

Ответ 11

Для тех, кто хочет добавить статический метод к встроенному объекту, например Date, легко

interface DateConstructor {
    fromServerDate: any
}

И теперь Date.fromServerDate(appt.changeDate) будет компилироваться отлично.