TypeScript中是否存在公共静态常量?我有一个看起来像这样的课程:
export class Library {
public static BOOK_SHELF_NONE: string = "None";
public static BOOK_SHELF_FULL: string = "Full";
}
在那堂课中,我可以Library.BOOK_SHELF_NONE
而且tsc不会抱怨。但是如果我尝试在其他地方使用类库,并尝试做同样的事情,它就无法识别它。
答案 0 :(得分:387)
如果你确实想要在现代浏览器中表现得更像静态常量值的东西(因为它不能被其他代码更改),你可以只为{{get
添加Library
访问者1}} class(这只适用于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
属性设置为新值的尝试是如何工作的。
在TypeScript 2.0中,您可以使用readonly
来获得非常相似的结果:
export class Library {
public static readonly BOOK_SHELF_NONE = "None";
public static readonly BOOK_SHELF_FULL = "Full";
}
语法更简单,更明显。但是,编译器会阻止更改而不是运行时(与第一个示例中的情况不同,根据演示,根本不允许更改)。
答案 1 :(得分:40)
您可以使用namespaces执行此操作,如下所示:
export namespace Library {
export const BOOK_SHELF_NONE: string = 'NONE';
}
然后你可以从其他任何地方导入它:
import {Library} from './Library';
console.log(Library.BOOK_SHELF_NONE);
如果你需要一个类,那么在命名空间中包含它:export class Book {...}
答案 2 :(得分:22)
以下是此TS片段编入的内容(通过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;
});
如您所见,定义为public static
的两个属性都只是附加到导出的函数(作为其属性);因此,只要您正确访问该功能本身,它们就应该是可访问的。
答案 3 :(得分:13)
同时这可以通过装饰器结合Object.freeze
或Object.defineProperty
来解决,我正在使用它,它比使用大量的吸气剂更漂亮。您可以直接复制/粘贴此TS Playground以查看其实际效果。 - 有两个选项
以下装饰器将注释的静态和非静态字段转换为“仅getter-properties”。
注意:如果没有初始值的实例变量被注释@final
,那么第一个分配的值(无论何时)将是最后一个。
// 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
});
}
}
作为上面装饰器的替代方案,还会有一个严格的版本,当有人试图为设置"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."
答案 4 :(得分:6)
谢谢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!)
答案 5 :(得分:2)
以下解决方案也适用于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!!!");
}
答案 6 :(得分:0)
您可以使用吸气剂,这样您的财产将只能读取。 示例:
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);
}
}
答案 7 :(得分:0)
只需在您的班级中“导出”变量和“导入”
import appConstants = require('../core/AppSettings');
console.log(appConstants.errStringMsg);
console.log(appConstants.GOOGLE_API_URL);
现在用它作为,
{{1}}