statique statique dans TypeScript

Existe-t-il des constantes statiques publiques dans TypeScript? J’ai un cours qui ressemble à:

export class Library { public static BOOK_SHELF_NONE: ssortingng = "None"; public static BOOK_SHELF_FULL: ssortingng = "Full"; } 

Dans cette classe, je peux faire Library.BOOK_SHELF_NONE et la tsc ne se plaint pas. Mais si j’essaie d’utiliser la bibliothèque de classes ailleurs et d’essayer de faire la même chose, cela ne le reconnaît pas.

Voici en quoi consiste l’extrait de code TS compilé (via TS Playground ):

 define(["require", "exports"], function(require, exports) { var Library = (function () { function Library() { } Library.BOOK_SHELF_NONE = "None"; Library.BOOK_SHELF_FULL = "Full"; return Library; })(); exports.Library = Library; }); 

Comme vous le voyez, les deux propriétés définies comme public static sont simplement attachées à la fonction exscope (comme ses propriétés); ils doivent donc être accessibles tant que vous accédez correctement à la fonction elle-même.

Si vous vouliez quelque chose qui ressemblerait plus à une valeur constante statique dans les navigateurs modernes (en ce sens qu’il ne peut pas être modifié par un autre code), vous pouvez append un accesseur get only à la classe Library (cela ne fonctionnera que pour les navigateurs ES5 +). NodeJS):

 export class Library { public static get BOOK_SHELF_NONE():ssortingng { return "None"; } public static get BOOK_SHELF_FULL():ssortingng { return "Full"; } } var x = Library.BOOK_SHELF_NONE; console.log(x); Library.BOOK_SHELF_NONE = "Not Full"; x = Library.BOOK_SHELF_NONE; console.log(x); 

Si vous l’exécutez, vous verrez comment la tentative de définir la propriété BOOK_SHELF_NONE sur une nouvelle valeur ne fonctionne pas.

2.0

Dans TypeScript 2.0, vous pouvez utiliser readonly pour obtenir des résultats très similaires:

 export class Library { public static readonly BOOK_SHELF_NONE = "None"; public static readonly BOOK_SHELF_FULL = "Full"; } 

La syntaxe est un peu plus simple et plus évidente. Cependant, le compilateur empêche les modifications plutôt que le temps d’exécution (contrairement au premier exemple, où la modification ne serait pas autorisée du tout, comme démontré).

Vous pouvez le faire en utilisant des espaces de noms , comme ceci:

 export namespace Library { export const BOOK_SHELF_NONE: ssortingng = 'NONE'; } 

Ensuite, vous pouvez l’importer de n’importe où ailleurs:

 import {Library} from './Library'; console.log(Library.BOOK_SHELF_NONE); 

Si vous avez besoin d’une classe, incluez-la également dans l’espace de noms: export class Book {...}

En attendant, cela peut être résolu par un décorateur en combinaison avec Object.freeze ou Object.defineProperty , je l’utilise, c’est un peu plus joli que d’utiliser des tonnes de getters. Vous pouvez copier / coller directement ce TS Playground pour le voir en action. – Il y a deux options


Rendre les champs individuels “finaux”

Le décorateur suivant convertit les deux champs statiques et non statiques annotés en “getter-only-properties”.

Remarque : Si une variable d’instance sans valeur initiale est annotée @final , la première valeur atsortingbuée (peu importe quand) sera la dernière.

 // example class MyClass { @final public finalProp: ssortingng = "You shall not change me!"; @final public static FINAL_FIELD: number = 75; public static NON_FINAL: ssortingng = "I am not final." } var myInstance: MyClass = new MyClass(); myInstance.finalProp = "Was I changed?"; MyClass.FINAL_FIELD = 123; MyClass.NON_FINAL = "I was changed."; console.log(myInstance.finalProp); // => You shall not change me! console.log(MyClass.FINAL_FIELD); // => 75 console.log(MyClass.NON_FINAL); // => I was changed. 

Le décorateur: Assurez-vous d’inclure ceci dans votre code!

 /** * Turns static and non-static fields into getter-only, and therefor renders them "final". * To use simply annotate the static or non-static field with: @final */ function final(target: any, propertyKey: ssortingng) { const value: any = target[propertyKey]; // if it currently has no value, then wait for the first setter-call // usually the case with non-static fields if (!value) { Object.defineProperty(target, propertyKey, { set: function (value: any) { Object.defineProperty(this, propertyKey, { get: function () { return value; }, enumerable: true, configurable: false }); }, enumerable: true, configurable: true }); } else { // else, set it immediatly Object.defineProperty(target, propertyKey, { get: function () { return value; }, enumerable: true }); } } 

En guise d’alternative au décorateur ci-dessus, il y aurait également une version ssortingcte de cette méthode, qui provoquerait même une erreur lorsque quelqu’un tenterait d’atsortingbuer une valeur au champ avec "use ssortingct"; être réglé. (Ce n’est que la partie statique)

 /** * Turns static fields into getter-only, and therefor renders them "final". * Also throws an error in ssortingct mode if the value is sortinged to be touched. * To use simply annotate the static field with: @ssortingctFinal */ function ssortingctFinal(target: any, propertyKey: ssortingng) { Object.defineProperty(target, propertyKey, { value: target[propertyKey], writable: false, enumerable: true }); } 

Rendre chaque champ statique “final”

Inconvénient possible: Cela ne fonctionnera que pour TOUS les statiques de cette classe ou pour aucune, mais ne peut pas être appliquée à des statiques spécifiques.

 /** * Freezes the annotated class, making every static 'final'. * Usage: * @StaticsFinal * class MyClass { * public static SOME_STATIC: ssortingng = "SOME_STATIC"; * //... * } */ function StaticsFinal(target: any) { Object.freeze(target); } 
 // Usage here @StaticsFinal class FreezeMe { public static FROZEN_STATIC: ssortingng = "I am frozen"; } class EditMyStuff { public static NON_FROZEN_STATIC: ssortingng = "I am frozen"; } // Test here FreezeMe.FROZEN_STATIC = "I am not frozen."; EditMyStuff.NON_FROZEN_STATIC = "I am not frozen."; console.log(FreezeMe.FROZEN_STATIC); // => "I am frozen." console.log(EditMyStuff.NON_FROZEN_STATIC); // => "I am not frozen." 

Merci WiredPrairie!

Juste pour développer un peu votre réponse, voici un exemple complet de définition d’une classe de constantes.

 // CYConstants.ts class CYConstants { public static get NOT_FOUND(): number { return -1; } public static get EMPTY_STRING(): ssortingng { return ""; } } export = CYConstants; 

Utiliser

 // main.ts import CYConstants = require("./CYConstants"); console.log(CYConstants.NOT_FOUND); // Prints -1 console.log(CYConstants.EMPTY_STRING); // Prints "" (Nothing!) 

La solution suivante fonctionne également à partir de TS 1.7.5.

 // Constancts.ts export const kNotFoundInArray = -1; export const AppConnectionError = new Error("The application was unable to connect!"); export const ReallySafeExtensions = ["exe", "virus", "1337h4x"]; 

Utiliser:

 // Main.ts import {ReallySafeExtensions, kNotFoundInArray} from "./Constants"; if (ReallySafeExtensions.indexOf("png") === kNotFoundInArray) { console.log("PNG's are really unsafe!!!"); } 

Il suffit simplement d’exporter la variable et d’importer dans votre classe

 export var GOOGLE_API_URL = 'https://www.googleapis.com/admin/directory/v1'; // default err ssortingng message export var errSsortingngMsg = 'Something went wrong'; 

Maintenant, utilisez-le comme,

 import appConstants = require('../core/AppSettings'); console.log(appConstants.errSsortingngMsg); console.log(appConstants.GOOGLE_API_URL); 

Vous pouvez utiliser un getter pour que votre propriété ne soit en train de lire. Exemple:

 export class MyClass { private _LEVELS = { level1: "level1", level2: "level2", level2: "level2" }; public get STATUSES() { return this._LEVELS; } } 

Utilisé dans une autre classe:

 import { MyClass } from "myclasspath"; class AnotherClass { private myClass = new MyClass(); tryLevel() { console.log(this.myClass.STATUSES.level1); } }