8 ответов:
следуйте ответу @Duncan @ Bartvds, здесь, чтобы обеспечить работоспособный способ после нескольких лет.
на данный момент после выпуска Typescript 1.5 (@Jun 15 '15), ваш полезный интерфейс
interface MyType { instanceMethod(); } interface MyTypeStatic { new():MyType; staticMethod(); }может быть реализован таким образом, с помощью декоратора.
/* class decorator */ function staticImplements<T>() { return (constructor: T) => {} } @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.
визуальный результат: Ошибка компиляции с подсказкой статического метода недостающий.
после реализации статического метода, подсказка для метода отсутствует.
компиляция прошла после выполнения как статического интерфейса, так и обычного интерфейса.
статические свойства обычно размещаются в (глобальном) конструкторе для объекта, тогда как ключевое слово "interface" применяется к экземплярам объекта.
предыдущий ответ, Конечно, правильный, если вы пишете класс в TypeScript. Это может помочь другим узнать, что если вы описываете объект, который уже реализован в другом месте, то глобальный конструктор, включая статические свойства, может быть объявлен следующим образом:
declare var myInterface : { new(): Interface; 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 }работающего пример
решение@duncan выше указания
new()для статического типа работает также с интерфейсами:interface MyType { instanceMethod(); } interface MyTypeStatic { new():MyType; staticMethod(); }
Если вы хотите определить статический класс (т. е. все методы/свойства статичны), вы можете сделать что-то вроде этого:
interface MyStaticClassInterface { foo():string; } var myStaticClass:MyStaticClassInterface = { foo() { return 'bar'; } };в этом случае статический "класс" на самом деле просто простой-ol'-js-объект, который реализует все методы
MyStaticClassInterface
Я нашел способ сделать это (без отделочников) для моего конкретного случая использования.
важная часть, которая проверяет статические члены
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);
Вы можете объединить интерфейс с пространством имен используя то же имя:
interface myInterface { } namespace myInterface { Name:string; }но этот интерфейс полезен только для того, чтобы знать, что у него есть свойство
Name. Вы не можете его реализовать.



Comments