C#のような構文が好きなので、従来のJSからTypeScriptに移行したかったのです。私の問題は、TypeScriptで静的クラスを宣言する方法を見つけることができないことです。
C#では、多くの場合、静的クラスを使用して変数とメソッドを整理し、オブジェクトをインスタンス化する必要なく、それらを名前付きクラスにまとめます。バニラJSでは、これを単純なJSオブジェクトで実行していました。
var myStaticClass = {
property: 10,
method: function(){}
}
TypeScriptでは、Cシャーピーアプローチを選びますが、TSには静的クラスは存在しないようです。この問題の適切な解決策は何ですか?
TypeScriptはC#ではないため、TypeScriptで必ずしもC#と同じ概念を期待するべきではありません。問題は、なぜ静的クラスが必要なのですか?
C#では、静的クラスは単にサブクラス化できないクラスであり、静的メソッドのみを含める必要があります。 C#では、クラスの外部で関数を定義することはできません。ただし、TypeScriptではこれが可能です。
関数/メソッドを名前空間(つまり、グローバルではない)に配置する方法を探している場合は、TypeScriptのモジュールの使用を検討できます。
module M {
var s = "hello";
export function f() {
return s;
}
}
そのため、外部からM.f()にアクセスできますが、sにはアクセスできず、モジュールを拡張できません。
詳細については、TypeScript specification を参照してください。
抽象クラスは、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
クラスの静的プロパティとメソッドの定義については、 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()
は静的(または「クラス」)メソッドです。
この質問はかなり古いですが、現在のバージョンの言語を活用する答えを残したかったです。残念ながら、静的クラスはまだTypeScriptに存在しませんが、外部からのクラスのインスタンス化を防ぐプライベートコンストラクターを使用して、わずかなオーバーヘッドで同様に動作するクラスを作成できます。
class MyStaticClass {
public static readonly property: number = 42;
public static myMethod(): void { /* ... */ }
private constructor() { /* noop */ }
}
このスニペットを使用すると、C#の対応物と同様の「静的」クラスを使用できますが、内部からインスタンス化できるという唯一の欠点があります。幸いなことに、プライベートコンストラクターでクラスを拡張することはできません。
これは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_ctor
でthis
を使用しないでください(明らかに)。
今日、同じユースケース(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();
これは私のために働いた。誰か他のより良い提案があれば、私たち全員にそれを聞かせてください!!!ありがとう...
C#などの言語の静的クラスは、データと関数をグループ化する他のトップレベルの構成体がないために存在します。ただし、JavaScriptではそうであるため、あなたのようにオブジェクトを宣言する方がはるかに自然です。クラスの構文をより厳密に模倣するために、次のようなメソッドを宣言できます。
const myStaticClass = {
property: 10,
method() {
}
}
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つの方法は、クラスの静的インスタンスを別のクラス内に保持することです。例えば:
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タイピングを追加できるという利点があります。さらに、クラス内のすべてのパラメーターの前に「静的」を追加する必要がなくなります。
私は似たようなものを探していて、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() );