wake-up-neo.com

Statische TypeScript-Klassen

Ich wollte von traditionellem JS zu TypeScript wechseln, weil ich die C # -ähnliche Syntax mag . Mein Problem ist, dass ich nicht herausfinden kann, wie statische Klassen in TypeScript deklariert werden.

In C # verwende ich häufig statische Klassen, um Variablen und Methoden zu organisieren und sie in einer benannten Klasse zusammenzufassen, ohne ein Objekt installieren zu müssen .. In Vanilla JS habe ich dies mit einem einfachen JS-Objekt gemacht:

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

In TypeScript würde ich mich lieber für meinen C-sharpy-Ansatz entscheiden, aber in TS ..__ gibt es scheinbar keine statischen Klassen. Was ist die passende Lösung für dieses Problem?

102
Rayjax

TypeScript ist nicht C #, daher sollten Sie nicht unbedingt die gleichen Konzepte von C # in TypeScript erwarten. Die Frage ist, warum wollen Sie statische Klassen?

In C # ist eine statische Klasse einfach eine Klasse, die nicht subklassifiziert werden kann und nur statische Methoden enthalten muss. C # erlaubt es nicht, Funktionen außerhalb von Klassen zu definieren. In TypeScript ist dies jedoch möglich.

Wenn Sie nach einer Möglichkeit suchen, Ihre Funktionen/Methoden in einem Namespace (d. H. Nicht global) zu platzieren, sollten Sie die Verwendung der Module von TypeScript in Betracht ziehen, z.

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

Damit können Sie auf M.f () extern zugreifen, aber nicht auf s, und Sie können das Modul nicht erweitern.

Weitere Informationen finden Sie in der TypeScript Spezifikation .

137
Marcus

Abstrakte Klassen waren seit TypeScript 1.6 ein erstklassiger Bürger von TypeScript. Sie können eine abstrakte Klasse nicht instanziieren.

Hier ist ein Beispiel:

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

Das Definieren statischer Eigenschaften und Methoden einer Klasse wird in 8.2.1 der TypeScript Language Specification beschrieben:

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); 
  } 
}

dabei ist Point.distance() eine statische (oder "Klassen") Methode.

69
Rob Raisch

Dies ist eine Möglichkeit:

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

__static_ctor ist ein sofort aufgerufener Funktionsausdruck. TypeScript gibt Code aus, um ihn am Ende der generierten Klasse aufzurufen.

Update: Für generische Typen in statischen Konstruktoren, auf die statische Member nicht mehr referenzieren dürfen, ist jetzt ein zusätzlicher Schritt erforderlich:

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

In jedem Fall können Sie natürlich den generischen Typ statischer Konstruktor after the-Klasse aufrufen, z.

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

Denken Sie daran, NIEMALS this in __static_ctor oben zu verwenden (offensichtlich).

7
James Wilkins

Diese Frage ist ziemlich veraltet, aber ich wollte eine Antwort hinterlassen, die die aktuelle Version der Sprache nutzt. Leider sind statische Klassen immer noch nicht in TypeScript vorhanden. Sie können jedoch eine Klasse schreiben, die sich nur mit einem geringen Aufwand mit einem privaten Konstruktor verhält, der die Instantiierung von Klassen von außen verhindert.

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

Mit diesem Snippet können Sie "statische" Klassen verwenden, die dem Gegenstück von C # ähneln, mit dem einzigen Nachteil, dass es immer noch möglich ist, sie von innen zu instanziieren. Glücklicherweise können Sie Klassen nicht mit privaten Konstruktoren erweitern.

4

Ich habe heute (31/07/2018) den gleichen Anwendungsfall erhalten und fand, dass dies eine Problemumgehung ist. Es basiert auf meiner Forschung und hat für mich funktioniert. Erwartung - Um Folgendes in TypeScript zu erreichen:

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

Ich tat dies:

//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();
        }
     }

Daher werden wir es wie folgt konsumieren:

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

Das hat bei mir funktioniert. Wenn jemand andere bessere Vorschläge hat, lass es uns alle hören !!! Vielen Dank...

4
KoRa

Statische Klassen in Sprachen wie C # existieren, da keine anderen Konstrukte auf oberster Ebene vorhanden sind, um Daten und Funktionen zu gruppieren. In JavaScript ist dies jedoch der Fall. Daher ist es viel natürlicher, ein Objekt wie Sie zu deklarieren. Um die Klassensyntax genauer nachzuahmen, können Sie Methoden wie folgt deklarieren:

const myStaticClass = {
    property: 10,

    method() {

    }
}
2
Yogu

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

Dies ist eine Möglichkeit, einen statischen Konstruktor zu "fälschen". Es ist nicht ohne Gefahren - siehe den referenzierten Codeplex-Punkt .

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

Eine Möglichkeit, dies zu erreichen, besteht darin, statische Instanzen einer Klasse in einer anderen Klasse zu haben. Zum Beispiel:

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();
}

Auf die Parameter kann dann mit Wrapper zugegriffen werden, ohne dass eine Instanz davon deklariert werden muss. Zum Beispiel:

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

Sie erhalten also die Vorteile des JavaScript-Typobjekts (wie in der ursprünglichen Frage beschrieben), jedoch mit den Vorteilen, dass Sie die TypeScript-Typisierung hinzufügen können. Darüber hinaus wird vermieden, dass vor allen Parametern der Klasse 'static' hinzugefügt werden muss.

1
Steve Roberts

Ich suchte nach etwas Ähnlichem und kam durch etwas namens Singleton Pattern.

Referenz: Singleton Pattern

Ich arbeite an einer BulkLoader-Klasse, um verschiedene Dateitypen und .__ zu laden. wollte das Singleton-Muster dafür verwenden. Auf diese Weise kann ich Dateien laden aus meiner Hauptanwendungsklasse und rufen Sie die geladenen Dateien problemlos ab aus anderen Klassen.

Es folgt ein einfaches Beispiel, wie Sie einen Score-Manager für ein Spiel erstellen können mit TypeScript und dem Singleton-Muster.

klasse 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;
}   }

Dann haben Sie überall in Ihren anderen Klassen Zugriff auf die Singleton von:

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