Я хотел перейти на TypeScript с традиционного JS, потому что мне нравится синтаксис, подобный C #. Моя проблема в том, что я не могу понять, как объявлять статические классы в TypeScript.
В C # я часто использую статические классы для организации переменных и методов, объединяя их в именованный класс, без необходимости инстанцировать объект. В vanilla JS я делал это с помощью простого объекта JS:
var myStaticClass = {
property: 10,
method: function(){}
}
В TypeScript я бы предпочел использовать свой подход C-sharpy, но кажется, что статических классов в TS не существует. Какое подходящее решение этой проблемы?
источник
.js
в вашhtml
. Так что, посколькуAngular 2
вы, вероятно, используетеSystem
... так и сделал быSystem.import("Folder/M");
(или как бы там ни был путь к скомпилированному.js
файлу) доbootstrap import
Абстрактные классы были первоклассными гражданами TypeScript начиная с TypeScript 1.6. Вы не можете создать абстрактный класс.
Вот пример:
export abstract class MyClass { public static myProp = "Hello"; public static doSomething(): string { return "World"; } } const okay = MyClass.doSomething(); //const errors = new MyClass(); // Error
источник
Singleton
предназначен для шаблона общей памяти того же экземпляра класса. Кроме того, статический класс не имеет экземпляра по определению, поэтому вы должны создать исключение, если клиент пытается его инициализировать.abstract
ключевое слово поддерживается в TypeScript.abstract
! @KimchiMan - отличная идея!Определение статических свойств и методов класса описано в разделе 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 #, с единственным недостатком, что их все еще можно создавать изнутри. К счастью, вы не можете расширять классы с помощью частных конструкторов.
источник
Это один способ:
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.___static_ctor(); }
В любом случае, конечно, вы можете просто вызвать статический конструктор универсального типа после класса, например:
class SomeClass<T> { static myStaticVariable = "whatever"; private __static_ctor = (() => { var example: SomeClass<T>; /* do static constructor stuff :) */ })(); } SomeClass.prototype.__static_ctor();
Только не забудьте использовать NEVER
this
в__static_ctor
выше (очевидно).источник
class SomeClass {}
генерирует конструктор - вряд ли стоит комментировать, как будто вводится новая проблема. ;) К вашему сведению: в JS нет настоящих «конструкторов» - только функции, у которых есть «this» при вызове объектов или черезnew
. Это существует не смотря ни на что для любого «класса».Сегодня у меня такой же вариант использования (31.07.2018), и я обнаружил, что это обходной путь. Он основан на моих исследованиях и у меня сработал. Ожидание - для достижения следующих целей в 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
Это способ «подделать» статический конструктор. Это небезопасно - см. Упомянутый элемент 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);
источник
Один из возможных способов добиться этого - иметь статические экземпляры класса внутри другого класса. Например:
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. Кроме того, это позволяет избежать добавления слова static перед всеми параметрами в классе.
источник
С внешними модулями ES6 это может быть достигнуто следующим образом:
// privately scoped array let arr = []; export let ArrayModule = { add: x => arr.push(x), print: () => console.log(arr), }
Это предотвращает использование внутренних модулей и пространств имен, что считается плохой практикой TSLint [1] [2] , разрешает частную и открытую область видимости и предотвращает инициализацию нежелательных объектов класса.
источник
Я искал что-то подобное и наткнулся на то, что называется
Singleton Pattern
.Ссылка: Singleton Pattern
источник
Вы также можете использовать ключевое слово
namespace
для организации ваших переменных, классов, методов и так далее. См. Документ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); } } }
источник