Подтвердить что ты не робот

TypeScript статические классы

Я хотел перейти к TypeScript из традиционного JS, потому что мне нравится синтаксис, похожий на С#. Моя проблема в том, что я не могу узнать, как объявлять статические классы в TypeScript.

В С# я часто использую статические классы для организации переменных и методов, объединяя их в именованный класс без необходимости создания объекта. В vanilla JS я использовал это с помощью простого объекта JS:

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

В TypeScript, я бы предпочел использовать мой подход C-sharpy, но кажется, что статические классы не существуют в TS.  Какое подходящее решение для этой проблемы?

4b9b3361

Ответ 1

TypeScript не является С#, поэтому вам не следует ожидать, что те же концепции С# в TypeScript обязательно. Вопрос в том, зачем вам статические классы?

В С# статический класс - это просто класс, который не может быть подклассифицирован и должен содержать только статические методы. С# не позволяет определять функции вне классов. Однако в TypeScript это возможно.

Если вы ищете способ разместить свои функции/методы в пространстве имен (т.е. не глобальном), вы можете рассмотреть возможность использования модулей TypeScript, например.

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

Чтобы вы могли получить доступ к M.f() извне, но не s, и вы не можете расширять модуль.

Подробнее см. TypeScript specification.

Ответ 2

Определение статических свойств и методов класса описано в 8.2.1 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() - статический (или "классный" ) метод.

Ответ 3

Чтобы сделать класс static-like в TypeScript, вы можете пометить все свойства и методы как статические, о чем упомянули некоторые люди, - но помимо этого вы также можете обеспечить, чтобы новые экземпляры класса генерировали исключение для предотвращения экземпляров создается. Это существенно заставляет класс использоваться только статическим образом, хотя ошибка - это время выполнения, а не время компиляции.

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

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

const x = MyClass.doSomething();
//const example = new MyClass(); // Error

Ответ 4

Это один из способов:

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

В любом случае, конечно, вы можете просто вызвать статический конструктор типового типа после класса, например:

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

Помните, что НИКОГДА не используйте this в __static_ctor выше (очевидно).

Ответ 5

См. http://www.basarat.com/2013/04/typescript-static-constructors-for.html

Это способ "подделать" статический конструктор. Это не без его опасностей - см. ссылка на элемент codeplex.

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

Ответ 6

Я искал что-то похожее и получил нечто вроде Singleton Pattern.

Ссылка: Шаблон Singleton

Я работаю над классом BulkLoader для загрузки различных типов файлов и хотел использовать шаблон Singleton для него. Таким образом, я могу загружать файлы из моего основного класса приложения и легко загружать загруженные файлы из других классов.

Ниже приведен простой пример того, как вы можете создать менеджера очков для игры с TypeScript и шаблоном Singleton.

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

Тогда в любом месте других классов вы получите доступ к Singleton by:

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

Ответ 7

Статические классы в таких языках, как С#, существуют, потому что нет других конструкций верхнего уровня для группировки данных и функций. В JavaScript, однако, они делают, и поэтому гораздо более естественно просто объявить объект, как вы. Чтобы более точно сопоставить синтаксис класса, вы можете объявить такие методы:

const myStaticClass = {
    property: 10,

    method() {

    }
}

Ответ 8

Одним из возможных способов достижения этого является наличие статических экземпляров класса в другом классе. Например:

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 ввода. Кроме того, он избегает добавления "статического" перед всеми параметрами в классе.

Ответ 9

Вы также можете использовать ключевое слово namespace для упорядочивания переменных, классов, методов и т.д. См. doc

namespace Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    const lettersRegexp = /^[A-Za-z]+$/;
    const numberRegexp = /^[0-9]+$/;

    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}