web-dev-qa-db-fra.com

Classes statiques TypeScript

Je voulais passer de JS traditionnel à TypeScript, car j'aime bien la syntaxe semblable à C # . Mon problème est que je ne parviens pas à déterminer comment déclarer des classes statiques dans TypeScript.

En C #, j'utilise souvent des classes statiques pour organiser des variables et des méthodes, en les regroupant dans une classe nommée, sans avoir besoin d'instatier un objet .

var myStaticClass = {
    property: 10,
    method: function(){}
}

Dans TypeScript, je préférerais utiliser l'approche C-sharpy, mais il semble que les classes statiques n'existent pas dans TS . Quelle est la solution appropriée à ce problème?

102
Rayjax

TypeScript n'est pas en C #, vous ne devez donc pas nécessairement vous attendre aux mêmes concepts de C # dans TypeScript. La question est pourquoi voulez-vous des classes statiques?

En C #, une classe statique est simplement une classe qui ne peut pas être sous-classée et doit contenir uniquement des méthodes statiques. C # ne permet pas de définir des fonctions en dehors des classes. En TypeScript, cela est toutefois possible.

Si vous cherchez un moyen de placer vos fonctions/méthodes dans un espace de noms (c'est-à-dire non global), vous pouvez envisager d'utiliser les modules de TypeScript, par exemple.

module M {
    var s = "hello";
    export function f() {
        return s;
    }
}

Pour que vous puissiez accéder à M.f () en externe, mais pas en s, et vous ne pouvez pas étendre le module.

Voir la TypeScript spécification pour plus de détails.

137
Marcus

Les classes abstraites sont des citoyens de première classe de TypeScript depuis TypeScript 1.6. Vous ne pouvez pas instancier une classe abstraite.

Voici un exemple:

export abstract class MyClass {         
    public static myProp = "Hello";

    public static doSomething(): string {
      return "World";
    }
}

const okay = MyClass.doSomething();

//const errors = new MyClass(); // Error
100
Fenton

La définition des propriétés et méthodes statiques d’une classe est décrite au 8.2.1 de la spécification de type TypeScript :

class Point { 
  constructor(public x: number, public y: number) { } 
  public distance(p: Point) { 
    var dx = this.x - p.x; 
    var dy = this.y - p.y; 
    return Math.sqrt(dx * dx + dy * dy); 
  } 
  static Origin = new Point(0, 0); 
  static distance(p1: Point, p2: Point) { 
    return p1.distance(p2); 
  } 
}

Point.distance() est une méthode statique (ou "classe").

69
Rob Raisch

C'est une façon:

class SomeClass {
    private static myStaticVariable = "whatever";
    private static __static_ctor = (() => { /* do static constructor stuff :) */ })();
}

__static_ctor Voici une expression de fonction immédiatement appelée. TypeScript affichera du code pour l'appeler à la fin de la classe générée.

Mise à jour: pour les types génériques des constructeurs statiques, qui ne sont plus autorisés à être référencés par des membres statiques, vous aurez besoin d'une étape supplémentaire maintenant:

class SomeClass<T> {
    static myStaticVariable = "whatever";
    private ___static_ctor = (() => { var someClass:SomeClass<T> ; /* do static constructor stuff :) */ })();
    private static __static_ctor = SomeClass.prototype.___ctor();
}

Dans tous les cas, vous pouvez bien sûr appeler le constructeur statique de type générique après la classe, tel que:

class SomeClass<T> {
    static myStaticVariable = "whatever";
    private __static_ctor = (() => { var example: SomeClass<T>; /* do static constructor stuff :) */ })();
}
SomeClass.prototype.__static_ctor();

Rappelez-vous simplement de NE JAMAIS utiliser this dans __static_ctor ci-dessus (évidemment).

7
James Wilkins

Cette question est assez ancienne mais je voulais laisser une réponse qui exploite la version actuelle du langage. Malheureusement, les classes statiques n'existent toujours pas dans TypeScript. Toutefois, vous pouvez écrire une classe qui se comporte de manière similaire avec seulement une petite surcharge utilisant un constructeur privé qui empêche l'instanciation des classes de l'extérieur.

class MyStaticClass {
    public static readonly property: number = 42;
    public static myMethod(): void { /* ... */ }
    private constructor() { /* noop */ }
}

Cet extrait de code vous permettra d'utiliser des classes "statiques" similaires à l'homologue C # avec le seul inconvénient qu'il est encore possible de les instancier de l'intérieur. Heureusement, vous ne pouvez pas étendre les classes avec des constructeurs privés.

4
Christian Ivicevic

J'ai eu le même cas d'utilisation aujourd'hui (31/07/2018) et j'ai trouvé que c'était une solution de contournement. Il est basé sur mes recherches et a fonctionné pour moi . Expectation - Pour atteindre les objectifs suivants en TypeScript:

var myStaticClass = {
    property: 10,
    method: function(){} 
}

J'ai fait ça:

//MyStaticMembers.ts
namespace MyStaticMembers {
        class MyStaticClass {
           static property: number = 10;
           static myMethod() {...}
        }
        export function Property(): number {
           return MyStaticClass.property;
        }
        export function Method(): void {
           return MyStaticClass.myMethod();
        }
     }

Nous allons donc le consommer comme ci-dessous:

//app.ts
/// <reference path="MyStaticMembers.ts" />
    console.log(MyStaticMembers.Property);
    MyStaticMembers.Method();

Cela a fonctionné pour moi. Si quelqu'un a d'autres suggestions plus intéressantes, s'il vous plaît, laissez-nous tous l'entendre !!! Merci ...

3
KoRa

Les classes statiques dans des langages tels que C # existent parce qu'il n'y a pas d'autres constructions de niveau supérieur pour regrouper des données et des fonctions. En JavaScript, cependant, ils le font et il est donc beaucoup plus naturel de simplement déclarer un objet comme vous l'avez fait. Pour imiter de plus près la syntaxe de la classe, vous pouvez déclarer des méthodes comme suit:

const myStaticClass = {
    property: 10,

    method() {

    }
}
2
Yogu

Voir http://www.basarat.com/2013/04/TypeScript-static-constructors-for.html

C'est un moyen de "simuler" un constructeur statique. Ce n’est pas sans danger - voir le élément codeplex référencé .

class Test {
    static foo = "orig";

    // Non void static function
    static stat() {
        console.log("Do any static construction here");
        foo = "static initialized";
        // Required to make function non void
        return null;
    }
    // Static variable assignment
    static statrun = Test.stat();
}

// Static construction will have been done:
console.log(Test.foo);
1
Simon_Weaver

Une façon possible d'y parvenir est d'avoir des instances statiques d'une classe dans une autre classe. Par exemple:

class SystemParams
{
  pageWidth:  number = 8270;
  pageHeight: number = 11690;  
}

class DocLevelParams
{
  totalPages: number = 0;
}

class Wrapper
{ 
  static System: SystemParams = new SystemParams();
  static DocLevel: DocLevelParams = new DocLevelParams();
}

Vous pouvez ensuite accéder aux paramètres à l'aide de Wrapper, sans avoir à en déclarer une instance. Par exemple:

Wrapper.System.pageWidth = 1234;
Wrapper.DocLevel.totalPages = 10;

Vous bénéficiez donc des avantages de l’objet de type JavaScript (comme décrit dans la question initiale), mais avec l’avantage de pouvoir ajouter le typage TypeScript. De plus, cela évite d'avoir à ajouter "statique" devant tous les paramètres de la classe.

1
Steve Roberts

Je cherchais quelque chose de similaire et je suis tombé sur quelque chose appelé le Singleton Pattern.

Référence: Singleton Pattern

Je travaille sur une classe BulkLoader pour charger différents types de fichiers et voulait utiliser le modèle Singleton pour cela. De cette façon, je peux charger des fichiers à partir de ma classe d’application principale et récupérer facilement les fichiers chargés des autres classes.

Voici un exemple simple pour créer un gestionnaire de score pour un jeu avec TypeScript et le motif Singleton.

classe SingletonClass {

private static _instance:SingletonClass = new SingletonClass();

private _score:number = 0;

constructor() {
    if(SingletonClass._instance){
        throw new Error("Error: Instantiation failed: Use SingletonDemo.getInstance() instead of new.");
    }
    SingletonClass._instance = this;
}

public static getInstance():SingletonClass
{
    return SingletonClass._instance;
}

public setScore(value:number):void
{
    this._score = value;
}

public getScore():number
{
    return this._score;
}

public addPoints(value:number):void
{
    this._score += value;
}

public removePoints(value:number):void
{
    this._score -= value;
}   }

Ensuite, n'importe où dans vos autres classes, vous aurez accès au Singleton par:

var scoreManager = SingletonClass.getInstance();
scoreManager.setScore(10); scoreManager.addPoints(1);
scoreManager.removePoints(2); console.log( scoreManager.getScore() );
0
Devin Stokes