TypeScript中的public static const

在TypeScript中是否存在公共静态常量? 我有一个类,看起来像:

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

在那个课上,我可以做Library.BOOK_SHELF_NONE和tsc不会抱怨。 但是,如果我尝试在其他地方使用类库,并尝试做同样的事情,它不认识它。

这是什么TS代码片段编译成(通过TS游乐场 ):

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

正如你看到的,这两个定义为public static属性只是附加到导出的函数(作为它的属性)。 因此,只要您正确访问函数本身,就应该可以访问它们。

如果你确实想要在现代浏览器中performance得更像是一个静态的常量值(因为它不能被其他代码所改变),你可以在Library类中添加一个只读的访问器(这只适用于ES5 +浏览器,的NodeJS):

 export class Library { public static get BOOK_SHELF_NONE():string { return "None"; } public static get BOOK_SHELF_FULL():string { 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); 

如果您运行它,您将看到如何尝试将BOOK_SHELF_NONE属性设置为新值不起作用。

2.0

在TypeScript 2.0中,你可以使用readonly来获得非常相似的结果:

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

语法有点简单和明显。 但是,编译器可以防止更改,而不是运行时间(不像第一个示例中那样,根本不允许更改)。

你可以使用命名空间来做到这一点:

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

那么你可以从其他地方导入它:

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

如果您需要一个类,并将其包含在命名空间中: export class Book {...}

同时这可以通过装饰器与Object.freezeObject.defineProperty结合来解决,我使用这个,比使用大量的getter稍微漂亮些。 您可以直接复制/粘贴到TS Playground,以便看到它在行动。 – 有两个选项


使个别领域“最终”

下面的装饰器将注释的静态和非静态字段都转换为“getter-only-properties”。

注意 :如果没有初始值的实例variables被@final@final ,那么第一个赋值(不pipe何时)将是最后一个。

 // example class MyClass { @final public finalProp: string = "You shall not change me!"; @final public static FINAL_FIELD: number = 75; public static NON_FINAL: string = "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. 

装饰者:确保你包含在你的代码!

 /** * 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: string) { 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 }); } } 

作为上面装饰器的替代scheme,还会有一个严格的版本,当有人试图用"use strict";来赋值字段时,甚至会抛出一个错误"use strict"; 被设置。 (虽然这只是静态部分)

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

使每个静态字段“最终”

可能的下行:这将只适用于该类的所有静态或无效,但不能应用于特定的静态。

 /** * Freezes the annotated class, making every static 'final'. * Usage: * @StaticsFinal * class MyClass { * public static SOME_STATIC: string = "SOME_STATIC"; * //... * } */ function StaticsFinal(target: any) { Object.freeze(target); } 
 // Usage here @StaticsFinal class FreezeMe { public static FROZEN_STATIC: string = "I am frozen"; } class EditMyStuff { public static NON_FROZEN_STATIC: string = "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." 

谢谢你WiredPrairie!

稍微扩展一下你的答案,下面是一个定义常量类的完整例子。

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

使用

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

以下解决scheme也适用于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"]; 

使用:

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

只需简单地在你的课堂上“导出”variables和“导入”即可

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

现在使用它,

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

你可以使用吸气剂,这样你的财产将只能读取。 例:

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

用于另一个类:

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