Я просто хочу оголосити статичну властивість в інтерфейсі typecript ? Я ніде про це не знайшов.
interface myInterface {
static Name:string;
}
Це можливо?
Я просто хочу оголосити статичну властивість в інтерфейсі typecript ? Я ніде про це не знайшов.
interface myInterface {
static Name:string;
}
Це можливо?
Відповіді:
Ви не можете визначити статичну властивість в інтерфейсі в 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);
extendsключового слова. Ви просто не можете розширити інтерфейс з класом (що вам потрібно зробити, щоб додати статичну властивість).
Дотримуйтесь відповіді @ Дункана @ Бартвдса, щоб тут було зрозуміло, як пройдуть роки.
На цей момент після виходу Typescript 1.5 (@ 15 червня 1515 р.) Ваш корисний інтерфейс
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() {}
}
Зверніться до мого коментаря у відкритому номері 13462 github .
візуальний результат: помилка компіляції з відсутньою підказкою про статичний метод.

Після впровадження статичного методу підказка про відсутність методу.

Компіляція проходила після того, як був виконаний і статичний, і звичайний інтерфейс.

Ви можете нормально визначити інтерфейс:
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
}
Робочий приклад
@staticImplements.
reply(msg: IBotMsg): Promise<IBotReply>
Статичні властивості зазвичай розміщуються на (глобальному) конструкторі для об'єкта, тоді як ключове слово "інтерфейс" застосовується до примірників об'єкта.
Попередня відповідь, безумовно, правильна, якщо ви пишете клас у TypeScript. Це може допомогти іншим зрозуміти, що якщо ви описуєте об'єкт, який вже реалізований в іншому місці, то глобальний конструктор, що включає статичні властивості, може бути оголошений так:
declare var myInterface : {
new(): Interface;
Name:string;
}
Статичні модифікатори не можуть з’являтися на типі елемента (помилка TypeScript TS1070). Ось чому я рекомендую використовувати абстрактний клас для вирішення місії:
Приклад
// 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());
Рішення @ duncan, вказане вище new()для статичного типу, також працює з інтерфейсами:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(як і в class Foo implements MyType). Статичний інтерфейс реально корисний лише у визначеннях при описі існуючого коду JS.
Якщо ви хочете визначити статичний клас (тобто всі методи / властивості є статичними), ви можете зробити щось подібне:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
У цьому випадку статичний "клас" насправді є просто звичайним об'єктом-ol'-js, який реалізує всі методи MyStaticClassInterface
Так, можливо. Ось рішення
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Fooдля визначення визначення класу? де Class Foo буде реалізовувати statMethod (), це здається трохи злому, особливо, оскільки простори імен зараз
waiting more feedback. Тож ви або чекаєте, поки статичні методи будуть додані в інтерфейс, або зробите це так.
export namespaceНасправді ваша реалізація класу? Це, здається, дуже згинає речі. Цікаво, що ще, що ламається в Класах?
Інший варіант, який не згаданий тут, - це визначення змінної з типом, що представляє статичний інтерфейс, і призначення йому виразу класу:
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
Ви можете об'єднати інтерфейс з простором імен, використовуючи те саме ім'я:
interface myInterface { }
namespace myInterface {
Name:string;
}
Але цей інтерфейс корисно лише знати, що його властивість має Name. Ви не можете його реалізувати.
Я знайшов спосіб зробити це (без декораторів) для мого конкретного випадку використання.
Важлива частина , яка перевіряє наявність статичних членів є 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);
Хоча статичне ключове слово не підтримується в інтерфейсі в Typescript, але ми можемо досягти цього, створивши function interfaceстатичний член.
У своєму наступному коді я створив функціональний інтерфейс, 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();
Я реалізував таке рішення, як Каміл Шот , і воно має небажаний ефект. У мене недостатньо репутації, щоб розмістити це як коментар, тому я публікую його тут, якщо хтось спробує це рішення і прочитає це.
Рішення таке:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
Однак використання виразу класу не дозволяє мені використовувати MyClassяк тип. Якщо я напишу щось на кшталт:
const myInstance: MyClass;
myInstanceвиявляється типу any, і мій редактор показує таку помилку:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
В кінцевому підсумку втрачаю важливішу типізацію, ніж ту, яку хотів досягти за допомогою інтерфейсу для статичної частини класу.
Розв’язання Валя за допомогою декоратора дозволяє уникнути цієї неприємності.