Je veux juste déclarer une propriété statique dans l' interface dactylographiée ? Je n'ai trouvé nulle part à ce sujet.
interface myInterface {
static Name:string;
}
C'est possible?
Je veux juste déclarer une propriété statique dans l' interface dactylographiée ? Je n'ai trouvé nulle part à ce sujet.
interface myInterface {
static Name:string;
}
C'est possible?
Réponses:
Vous ne pouvez pas définir une propriété statique sur une interface dans TypeScript.
Supposons que vous vouliez changer l' Dateobjet, plutôt que d'essayer d'ajouter aux définitions de Date, vous pouvez l'envelopper ou simplement créer votre classe de date enrichie pour faire ce qui Datene fait pas.
class RichDate {
public static MinValue = new Date();
}
Étant donné que Date est une interface dans TypeScript, vous ne pouvez pas l'étendre avec une classe utilisant le extendsmot - clé, ce qui est un peu dommage car ce serait une bonne solution si date était une classe.
Si vous souhaitez étendre l'objet Date pour fournir une MinValuepropriété sur le prototype, vous pouvez:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
Appelé en utilisant:
var x = new Date();
console.log(x.MinValue);
Et si vous voulez le rendre disponible sans instance, vous pouvez aussi ... mais c'est un peu difficile.
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
Appelé en utilisant:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
extendsmot - clé. Vous ne pouvez tout simplement pas étendre une interface avec une classe (ce que vous auriez besoin de faire pour ajouter une propriété statique).
Suivez la réponse de @ Duncan @ Bartvds, ici pour fournir un moyen pratique après des années.
À ce stade, après la sortie de Typescript 1.5 (@Jun 15 '15), votre interface utile
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
peut être mis en œuvre de cette façon avec l'aide du décorateur.
/* 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() {}
}
Reportez-vous à mon commentaire sur github open issue 13462 .
résultat visuel: erreur de compilation avec un indice de méthode statique manquant.

Une fois la méthode statique implémentée, un indice pour la méthode manquante.

Compilation réussie après que l'interface statique et l'interface normale soient remplies.

Vous pouvez définir l'interface normalement:
interface MyInterface {
Name:string;
}
mais tu ne peux pas simplement faire
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
Pour exprimer qu'une classe doit suivre cette interface pour ses propriétés statiques, vous avez besoin d'un peu de ruse:
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
Vous pouvez même garder le nom de la classe, TypeScript (2.0) ne vous dérangera pas:
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
Si vous souhaitez hériter de nombreuses interfaces de manière statique, vous devrez d'abord les fusionner dans une nouvelle:
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
}
Ou si vous ne voulez pas nommer l'interface fusionnée, vous pouvez faire:
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
}
Exemple de travail
@staticImplements.
reply(msg: IBotMsg): Promise<IBotReply>
Les propriétés statiques sont généralement placées sur le constructeur (global) de l'objet, tandis que le mot clé "interface" s'applique aux instances de l'objet.
La réponse précédente donnée est bien sûr correcte si vous écrivez la classe en TypeScript. Cela peut aider les autres à savoir que si vous décrivez un objet qui est déjà implémenté ailleurs, alors le constructeur global incluant les propriétés statiques peut être déclaré comme ceci:
declare var myInterface : {
new(): Interface;
Name:string;
}
Les modificateurs statiques ne peuvent pas apparaître sur un membre de type (erreur TypeScript TS1070). C'est pourquoi je recommande d'utiliser une classe abstraite pour résoudre la mission:
Exemple
// 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());
La solution de @ duncan ci-dessus en spécifiant new()pour le type statique fonctionne également avec les interfaces:
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implement?
MyType(comme dans class Foo implements MyType). L'interface statique n'est vraiment utile que dans les définitions, lors de la description du code JS existant.
Si vous cherchez à définir une classe statique (c'est-à-dire que toutes les méthodes / propriétés sont statiques), vous pouvez faire quelque chose comme ceci:
interface MyStaticClassInterface {
foo():string;
}
var myStaticClass:MyStaticClassInterface = {
foo() {
return 'bar';
}
};
Dans ce cas, la "classe" statique n'est en réalité qu'un simple objet-ol'-js, qui implémente toutes les méthodes de MyStaticClassInterface
Oui c'est possible. Voici la solution
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Foode noms pour remplacer une définition de classe? où la classe Foo implémenterait le statMethod () cela semble un peu un hack, d'autant plus que les espaces de noms sont en quelque sorte obsolètes maintenant ...
waiting more feedback. Vous attendez donc que des méthodes statiques soient ajoutées à l'interface ou procédez de cette façon.
export namespaceest en fait votre implémentation de classe? Cela semble plier beaucoup les choses. Je me demande quoi d'autre qui casse dans les classes?
Une autre option non mentionnée ici consiste à définir une variable avec un type représentant une interface statique et à lui affecter une expression de classe:
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() { }
}
L'effet est le même qu'en réponse avec les décorateurs , mais sans frais généraux des décorateurs
Suggestion / discussion pertinente sur GitHub
Vous pouvez fusionner l'interface avec l'espace de noms en utilisant le même nom:
interface myInterface { }
namespace myInterface {
Name:string;
}
Mais cette interface n'est utile que pour savoir qu'elle possède une propriété Name. Vous ne pouvez pas l'implémenter.
J'ai trouvé un moyen de le faire (sans décorateurs) pour mon cas d'utilisation spécifique.
La partie importante qui vérifie les membres statiques est IObjectClasset utilise cls: IObjectClass<T>dans la createObjectméthode:
//------------------------
// 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);
Bien que le mot-clé statique ne soit pas pris en charge dans l'interface de Typescript, nous pouvons y parvenir en créant un function interfacequi a un membre statique.
Dans mon code suivant, j'ai créé une interface de fonction Factoryqui a deux membres statiques serialNumberet 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();
J'ai implémenté une solution comme celle de Kamil Szot , et elle a un effet indésirable. Je n'ai pas assez de réputation pour publier ceci comme un commentaire, donc je le poste ici au cas où quelqu'un essayerait cette solution et lirait ceci.
La solution est:
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
Cependant, l'utilisation d'une expression de classe ne me permet pas de l'utiliser MyClasscomme type. Si j'écris quelque chose comme:
const myInstance: MyClass;
myInstances'avère être de type any, et mon éditeur affiche l'erreur suivante:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
Je finis par perdre un typage plus important que celui que je voulais réaliser avec l'interface pour la partie statique de la classe.
La solution de Val utilisant un décorateur évite cet écueil.