Chcę tylko zadeklarować właściwość statyczną w interfejsie maszynopisu ? Nie znalazłem nigdzie w związku z tym.
interface myInterface {
static Name:string;
}
Czy to możliwe?
Chcę tylko zadeklarować właściwość statyczną w interfejsie maszynopisu ? Nie znalazłem nigdzie w związku z tym.
interface myInterface {
static Name:string;
}
Czy to możliwe?
Odpowiedzi:
Nie można zdefiniować właściwości statycznej w interfejsie w TypeScript.
Załóżmy, że chcesz zmienić Dateobiekt, zamiast próbować dodawać go do definicji Date, możesz go opakować lub po prostu utworzyć klasę bogatej daty, aby robić rzeczy, które Datenie robią.
class RichDate {
public static MinValue = new Date();
}
Ponieważ Date jest interfejsem w TypeScript, nie można go rozszerzyć o klasę za pomocą extendssłowa kluczowego, co jest trochę wstydem, ponieważ byłoby to dobre rozwiązanie, gdyby date było klasą.
Jeśli chcesz przedłużyć obiekt Date, aby udostępnić MinValuewłaściwość prototypowi, możesz:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
Zadzwoniono za pomocą:
var x = new Date();
console.log(x.MinValue);
A jeśli chcesz udostępnić go bez instancji, możesz też ... ale jest to trochę wybredne.
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
Zadzwoniono za pomocą:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
extendssłowa kluczowego. Po prostu nie możesz rozszerzyć interfejsu o klasę (co musiałbyś zrobić, aby dodać właściwość statyczną).
Postępuj zgodnie z odpowiedzią @ Duncan's @ Bartvds, aby zapewnić praktyczny sposób po upływie lat.
W tym momencie po wydaniu Typescript 1.5 (@ Jun 15 '15), Twój pomocny interfejs
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
można w ten sposób zrealizować przy pomocy dekoratora.
/* 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() {}
}
Zobacz mój komentarz na github open issue 13462 .
wynik wizualny: błąd kompilacji z brakiem śladu metody statycznej.

Po zaimplementowaniu metody statycznej wskazówka dotycząca metody brakującej.

Kompilacja przeszła po spełnieniu zarówno statycznego, jak i normalnego interfejsu.

Możesz normalnie zdefiniować interfejs:
interface MyInterface {
Name:string;
}
ale nie możesz tak po prostu zrobić
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
Aby wyrazić, że klasa powinna podążać za tym interfejsem ze względu na swoje właściwości statyczne, potrzebujesz trochę sztuczki:
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
Możesz nawet zachować nazwę klasy, TypeScript (2.0) nie będzie miał nic przeciwko:
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
Jeśli chcesz dziedziczyć z wielu interfejsów statycznie, musisz najpierw scalić je w nowy:
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
}
Lub jeśli nie chcesz nazywać scalonego interfejsu, możesz zrobić:
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
}
Przykład roboczy
@staticImplements.
reply(msg: IBotMsg): Promise<IBotReply>
Właściwości statyczne są zwykle umieszczane w (globalnym) konstruktorze obiektu, podczas gdy słowo kluczowe „interface” odnosi się do instancji obiektu.
Poprzednia udzielona odpowiedź jest oczywiście poprawna, jeśli piszesz klasę w języku TypeScript. Innym może pomóc wiedzieć, że jeśli opisujesz obiekt, który został już zaimplementowany w innym miejscu, to globalny konstruktor zawierający właściwości statyczne można zadeklarować w następujący sposób:
declare var myInterface : {
new(): Interface;
Name:string;
}
Modyfikatory statyczne nie mogą pojawić się w elemencie typu (błąd TypeScript TS1070). Dlatego do rozwiązania misji polecam użyć klasy abstrakcyjnej:
Przykład
// 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());
Rozwiązanie @ duncan powyżej, określając new()typ statyczny, działa również z interfejsami:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(jak w class Foo implements MyType). Interfejs statyczny jest naprawdę przydatny tylko w definicjach, podczas opisywania istniejącego kodu JS.
Jeśli chcesz zdefiniować klasę statyczną (tj. Wszystkie metody / właściwości są statyczne), możesz zrobić coś takiego:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
W tym przypadku statyczna „klasa” jest w rzeczywistości zwykłym obiektem-ol'-js, który implementuje wszystkie metody MyStaticClassInterface
Tak to mozliwe. Oto rozwiązanie
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Foodo zastępowania definicji klasy? gdzie Class Foo zaimplementowałaby statMethod (), wydaje się to trochę hackem, szczególnie, ponieważ przestrzenie nazw są teraz trochę przestarzałe ...
waiting more feedback. Więc albo poczekaj, aż statyczne metody zostaną dodane do interfejsu, albo zrób w ten sposób.
export namespacefaktycznie jest implementacja Twojej klasy? To wydaje się bardzo naginać sprawy. Zastanawiam się, co jeszcze się psuje w klasach?
Inną opcją niewymienioną tutaj jest zdefiniowanie zmiennej o typie reprezentującym interfejs statyczny i przypisanie do niej wyrażenia klasowego:
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() { }
}
Efekt jest taki sam jak w przypadku odpowiedzi z dekoratorami , ale bez narzutu dekoratorów
Odpowiednia sugestia / dyskusja na GitHub
Możesz połączyć interfejs z przestrzenią nazw używając tej samej nazwy:
interface myInterface { }
namespace myInterface {
Name:string;
}
Ale ten interfejs jest przydatny tylko po to, aby wiedzieć, że ma właściwość Name. Nie możesz tego zaimplementować.
Znalazłem sposób, aby to zrobić (bez dekoratorów) dla mojego konkretnego przypadku użycia.
Ważną częścią sprawdzającą statyczne elementy członkowskie jest IObjectClassi używana cls: IObjectClass<T>w createObjectmetodzie:
//------------------------
// 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);
Chociaż statyczne słowo kluczowe nie jest obsługiwane w interfejsie w Typescript, ale możemy to osiągnąć, tworząc element, function interfacektóry ma statyczny element członkowski.
W poniższym kodzie utworzyłem interfejs funkcji, Factoryktóry ma dwa statyczne elementy członkowskie serialNumberi 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();
Wdrożyłem takie rozwiązanie jak Kamil Szot i ma to niepożądany efekt. Nie mam wystarczającej reputacji, aby opublikować to jako komentarz, więc zamieszczam go tutaj na wypadek, gdyby ktoś próbował tego rozwiązania i czytał.
Rozwiązaniem jest:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
Jednak użycie wyrażenia klasy nie pozwala mi używać MyClassjako typu. Jeśli napiszę coś takiego:
const myInstance: MyClass;
myInstanceokazuje się być typowy any, a mój edytor wyświetla następujący błąd:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
Ostatecznie tracę ważniejsze pisanie niż to, które chciałem osiągnąć z interfejsem dla statycznej części klasy.
Rozwiązanie Val wykorzystujące dekorator pozwala uniknąć tej pułapki.