Ich möchte nur eine statische Eigenschaft in der Typoskript- Schnittstelle deklarieren . Ich habe diesbezüglich nichts gefunden.
interface myInterface {
static Name:string;
}
Ist es möglich?
Ich möchte nur eine statische Eigenschaft in der Typoskript- Schnittstelle deklarieren . Ich habe diesbezüglich nichts gefunden.
interface myInterface {
static Name:string;
}
Ist es möglich?
Antworten:
Sie können in TypeScript keine statische Eigenschaft für eine Schnittstelle definieren.
Angenommen, Sie möchten das DateObjekt ändern , anstatt zu versuchen, es zu den Definitionen von hinzuzufügen. DateSie können es umbrechen oder einfach Ihre Rich-Date-Klasse erstellen, um die Aufgaben auszuführen, Datedie nicht ausgeführt werden.
class RichDate {
public static MinValue = new Date();
}
Da Date eine Schnittstelle in TypeScript ist, können Sie es nicht mit einer Klasse mit dem extendsSchlüsselwort erweitern, was etwas schade ist, da dies eine gute Lösung wäre, wenn date eine Klasse wäre.
Wenn Sie das Date-Objekt erweitern möchten, um eine MinValueEigenschaft für den Prototyp bereitzustellen , können Sie:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
Aufgerufen mit:
var x = new Date();
console.log(x.MinValue);
Und wenn Sie es ohne Instanz verfügbar machen möchten, können Sie es auch ... aber es ist ein bisschen pingelig.
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
Aufgerufen mit:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
extendsSchlüsselworts erweitern. Sie können eine Schnittstelle einfach nicht mit einer Klasse erweitern (was Sie tun müssten, um eine statische Eigenschaft hinzuzufügen).
Folgen Sie der Antwort von @ Duncan @ Bartvds, um nach Jahren einen praktikablen Weg zu finden.
An diesem Punkt nach der Veröffentlichung von Typescript 1.5 (@Jun 15 '15) ist Ihre hilfreiche Oberfläche
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
kann auf diese Weise mit Hilfe des Dekorateurs implementiert werden.
/* 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() {}
}
Siehe meinen Kommentar bei Github Open Issue 13462 .
visuelles Ergebnis: Kompilierungsfehler mit einem Hinweis auf fehlende statische Methode.

Nach der Implementierung der statischen Methode fehlt ein Hinweis auf die fehlende Methode.

Die Kompilierung wurde bestanden, nachdem sowohl die statische als auch die normale Schnittstelle erfüllt waren.

Sie können die Schnittstelle normal definieren:
interface MyInterface {
Name:string;
}
aber du kannst es nicht einfach tun
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
Um auszudrücken, dass eine Klasse aufgrund ihrer statischen Eigenschaften dieser Schnittstelle folgen sollte, müssen Sie einige Tricks ausführen:
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
Sie können sogar den Namen der Klasse behalten, TypeScript (2.0) hat nichts dagegen:
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
Wenn Sie statisch von vielen Schnittstellen erben möchten, müssen Sie diese zuerst zu einer neuen zusammenführen:
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
}
Oder wenn Sie die zusammengeführte Schnittstelle nicht benennen möchten, können Sie Folgendes tun:
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>
Statische Eigenschaften werden normalerweise im (globalen) Konstruktor für das Objekt platziert, während das Schlüsselwort "interface" für Instanzen des Objekts gilt.
Die vorherige Antwort ist natürlich richtig, wenn Sie die Klasse in TypeScript schreiben. Es kann anderen helfen zu wissen, dass, wenn Sie ein Objekt beschreiben, das bereits an anderer Stelle implementiert ist, der globale Konstruktor einschließlich der statischen Eigenschaften wie folgt deklariert werden kann:
declare var myInterface : {
new(): Interface;
Name:string;
}
Statische Modifikatoren können auf einem Typelement nicht angezeigt werden (TypeScript-Fehler TS1070). Deshalb empfehle ich, eine abstrakte Klasse zu verwenden, um die Mission zu lösen:
Beispiel
// 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());
Die oben angegebene Lösung von @ duncan new()für den statischen Typ funktioniert auch mit Schnittstellen:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(wie in class Foo implements MyType) implementieren . Die statische Schnittstelle ist nur in Definitionen wirklich nützlich, wenn vorhandener JS-Code beschrieben wird.
Wenn Sie eine statische Klasse definieren möchten (dh alle Methoden / Eigenschaften sind statisch), können Sie Folgendes tun:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
In diesem Fall ist die statische "Klasse" wirklich nur ein einfaches-ol'-js-Objekt, das alle Methoden von implementiert MyStaticClassInterface
Ja, es ist möglich. Hier ist die Lösung
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Fooum für eine Klassendefinition einzutreten? Wo Class Foo die statMethod () implementieren würde, scheint dies ein bisschen
waiting more feedback. Sie warten entweder, bis statische Methoden zur Schnittstelle hinzugefügt wurden, oder tun dies auf diese Weise.
export namespaceist eigentlich deine Klassenimplementierung? Das scheint die Dinge sehr zu verbiegen. Ich frage mich, was sonst noch in Klassen bricht?
Eine andere Option, die hier nicht erwähnt wird, besteht darin, eine Variable mit einem Typ zu definieren, der die statische Schnittstelle darstellt, und ihr einen Klassenausdruck zuzuweisen:
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() { }
}
Der Effekt ist der gleiche wie bei der Antwort mit Dekorateuren , jedoch ohne Overhead von Dekorateuren
Relevanter Vorschlag / Diskussion auf GitHub
Sie können die Schnittstelle mit dem Namespace unter demselben Namen zusammenführen:
interface myInterface { }
namespace myInterface {
Name:string;
}
Diese Schnittstelle ist jedoch nur nützlich, um zu wissen, dass sie über eine Eigenschaft verfügt Name. Sie können es nicht implementieren.
Ich habe einen Weg gefunden, dies (ohne Dekorateure) für meinen speziellen Anwendungsfall zu tun.
Der wichtige Teil, der nach statischen Elementen sucht, ist IObjectClassund verwendet cls: IObjectClass<T>in der createObjectMethode:
//------------------------
// 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);
Obwohl das statische Schlüsselwort in der Schnittstelle in Typescript nicht unterstützt wird, können wir es erreichen, indem wir ein statisches Element mit statischem Element erstellen function interface.
In meinem folgenden Code habe ich eine Funktionsschnittstelle erstellt Factory, die zwei statische ElementeserialNumber und printSerial enthält .
// 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();
Ich habe eine Lösung wie die von Kamil Szot implementiert , die einen unerwünschten Effekt hat. Ich habe nicht genug Ruf, um dies als Kommentar zu posten, also poste ich es hier, falls jemand diese Lösung versucht und dies liest.
Die Lösung ist:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
Die Verwendung eines Klassenausdrucks erlaubt mir jedoch nicht, ihn MyClassals Typ zu verwenden. Wenn ich so etwas schreibe wie:
const myInstance: MyClass;
myInstanceEs stellt sich heraus, dass es sich um einen Typ handelt any, und mein Editor zeigt den folgenden Fehler an:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
Am Ende verliere ich eine wichtigere Eingabe als die, die ich mit der Schnittstelle für den statischen Teil der Klasse erreichen wollte.
Die Lösung von Val mit einem Dekorateur vermeidet diese Gefahr.