web-dev-qa-db-ja.com

TypeScript静的クラス

C#のような構文が好きなので、従来のJSからTypeScriptに移行したかったのです。私の問題は、TypeScriptで静的クラスを宣言する方法を見つけることができないことです。

C#では、多くの場合、静的クラスを使用して変数とメソッドを整理し、オブジェクトをインスタンス化する必要なく、それらを名前付きクラスにまとめます。バニラJSでは、これを単純なJSオブジェクトで実行していました。

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

TypeScriptでは、Cシャーピーアプローチを選びますが、TSには静的クラスは存在しないようです。この問題の適切な解決策は何ですか?

111
Rayjax

TypeScriptはC#ではないため、TypeScriptで必ずしもC#と同じ概念を期待するべきではありません。問題は、なぜ静的クラスが必要なのですか?

C#では、静的クラスは単にサブクラス化できないクラスであり、静的メソッドのみを含める必要があります。 C#では、クラスの外部で関数を定義することはできません。ただし、TypeScriptではこれが可能です。

関数/メソッドを名前空間(つまり、グローバルではない)に配置する方法を探している場合は、TypeScriptのモジュールの使用を検討できます。

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

そのため、外部からM.f()にアクセスできますが、sにはアクセスできず、モジュールを拡張できません。

詳細については、TypeScript specification を参照してください。

145
Marcus

抽象クラスは、TypeScript 1.6以降、TypeScriptの第一級市民です。抽象クラスをインスタンス化することはできません。

以下に例を示します。

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

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

const okay = MyClass.doSomething();

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

クラスの静的プロパティとメソッドの定義については、 TypeScript言語仕様 の8.2.1で説明されています。

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()は静的(または「クラス」)メソッドです。

70
Rob Raisch

この質問はかなり古いですが、現在のバージョンの言語を活用する答えを残したかったです。残念ながら、静的クラスはまだTypeScriptに存在しませんが、外部からのクラスのインスタンス化を防ぐプライベートコンストラクターを使用して、わずかなオーバーヘッドで同様に動作するクラスを作成できます。

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

このスニペットを使用すると、C#の対応物と同様の「静的」クラスを使用できますが、内部からインスタンス化できるという唯一の欠点があります。幸いなことに、プライベートコンストラクターでクラスを拡張することはできません。

8

これは1つの方法です。

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

__static_ctorは、すぐに呼び出される関数式です。 TypeScriptは、生成されたクラスの最後に呼び出すコードを出力します。

更新:静的メンバーによる参照が許可されなくなった静的コンストラクターのジェネリック型については、追加の手順が必要になります。

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

いずれにせよ、もちろん、ジェネリック型の静的コンストラクターを呼び出すことができますafterクラスなど:

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

上記の__static_ctorthisを使用しないでください(明らかに)。

7
James Wilkins

今日、同じユースケース(2018年7月31日)を取得し、これが回避策であることがわかりました。それは私の研究に基づいており、私のために働いた。 期待値-TypeScriptで以下を実現するには:

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

これは私がしました:

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

したがって、以下のように消費します。

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

これは私のために働いた。誰か他のより良い提案があれば、私たち全員にそれを聞かせてください!!!ありがとう...

4
KoRa

C#などの言語の静的クラスは、データと関数をグループ化する他のトップレベルの構成体がないために存在します。ただし、JavaScriptではそうであるため、あなたのようにオブジェクトを宣言する方がはるかに自然です。クラスの構文をより厳密に模倣するために、次のようなメソッドを宣言できます。

const myStaticClass = {
    property: 10,

    method() {

    }
}
3
Yogu

http://www.basarat.com/2013/04/TypeScript-static-constructors-for.html を参照してください

これは、静的コンストラクターを「偽造」する方法です。危険がないわけではありません- 参照されるコードプレックス項目 を参照してください。

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

これを実現する1つの方法は、クラスの静的インスタンスを別のクラス内に保持することです。例えば:

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

その後、Wrapperを使用して、インスタンスを宣言することなくパラメーターにアクセスできます。例えば:

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

したがって、JavaScriptタイプオブジェクトの利点(元の質問で説明)を利用できますが、TypeScriptタイピングを追加できるという利点があります。さらに、クラス内のすべてのパラメーターの前に「静的」を追加する必要がなくなります。

1
Steve Roberts

私は似たようなものを探していて、Singleton Patternと呼ばれるものに出くわしました。

参照: シングルトンパターン

BulkLoaderクラスでさまざまなタイプのファイルをロードするために作業しており、そのためにシングルトンパターンを使用したいと考えていました。この方法で、メインアプリケーションクラスからファイルをロードし、ロードしたファイルを他のクラスから簡単に取得できます。

以下は、TypeScriptとシングルトンパターンを使用してゲームのスコアマネージャーを作成する簡単な例です。

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

次に、他のクラスのどこからでもシングルトンにアクセスできます:

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