如何实现类常量?

在TypeScript中,const关键字不能用于声明类属性。这样做会导致编译器报错“类成员不能有'const'关键字”。

我发现自己需要在代码中明确指出不应该更改某个属性。我希望IDE或编译器在声明属性后,如果我试图将新值赋给属性时出错。你们是怎么做到的?

我目前正在使用只读属性,但我是Typescript(和JavaScript)的新手,不知道是否有更好的方法:

get MY_CONSTANT():number {return 10};

我使用的是typescript 1.8。建议吗?

PS:我现在使用的是typescript 2.0.3,所以我接受了大卫的回答

468350 次浏览

常量可以在类外声明,在类内使用。否则,get属性是一个很好的解决方案

const MY_CONSTANT: string = "wazzup";


export class MyClass {


public myFunction() {


alert(MY_CONSTANT);
}
}

TypeScript 2.0有# EYZ0修饰符:

class MyClass {
readonly myReadOnlyProperty = 1;


myMethod() {
console.log(this.myReadOnlyProperty);
this.myReadOnlyProperty = 5; // error, readonly
}
}


new MyClass().myReadOnlyProperty = 5; // error, readonly

它不是一个确切的常数,因为它允许在构造函数中赋值,但这很可能不是一个大问题。

可选择的解决方案

另一种方法是使用static关键字和readonly:

class MyClass {
static readonly myReadOnlyProperty = 1;


constructor() {
MyClass.myReadOnlyProperty = 5; // error, readonly
}


myMethod() {
console.log(MyClass.myReadOnlyProperty);
MyClass.myReadOnlyProperty = 5; // error, readonly
}
}


MyClass.myReadOnlyProperty = 5; // error, readonly

这样做的好处是不能在构造函数中赋值,只存在于一个地方。

Angular 2提供了一个非常好的特性,叫做Opaque Constants。 创建类&

.

.
import { OpaqueToken } from "@angular/core";


export let APP_CONFIG = new OpaqueToken("my.config");


export interface MyAppConfig {
apiEndpoint: string;
}


export const AppConfig: MyAppConfig = {
apiEndpoint: "http://localhost:8080/api/"
};

将它注入providers in app.module.ts < / p >

您将能够跨每个组件使用它。

Angular 4的编辑:

对于Angular 4,新概念是注入令牌&不透明令牌在Angular 4中已弃用。

注入令牌在不透明令牌的基础上增加了功能,它允许通过TypeScript泛型在令牌上附加类型信息,加上注入令牌,不需要添加@Inject

示例代码

使用不透明令牌

const API_URL = new OpaqueToken('apiUrl'); //no Type Check




providers: [
{
provide: DataService,
useFactory: (http, apiUrl) => {
// create data service
},
deps: [
Http,
new Inject(API_URL) //notice the new Inject
]
}
]

Angular 4使用注入令牌

const API_URL = new InjectionToken<string>('apiUrl'); // generic defines return value of injector




providers: [
{
provide: DataService,
useFactory: (http, apiUrl) => {
// create data service
},
deps: [
Http,
API_URL // no `new Inject()` needed!
]
}
]

注入令牌是在不透明令牌的基础上设计的。不透明令牌在Angular 4中已弃用。

你可以在你的声明中用readonly修饰符标记属性:

export class MyClass {
public static readonly MY_PUBLIC_CONSTANT = 10;
private static readonly myPrivateConstant = 5;
}

@see # EYZ0

要么将readOnly修饰符与需要声明的常量一起使用,要么在类外声明一个常量,然后使用get操作符专门在所需的类中使用它。

为此你可以使用readonly修饰符。对象属性readonly只能在对象初始化时赋值。

课堂上的例子:

class Circle {
readonly radius: number;


constructor(radius: number) {
this.radius = radius;
}


get area() {
return Math.PI * this.radius * 2;
}
}


const circle = new Circle(12);
circle.radius = 12; // Cannot assign to 'radius' because it is a read-only property.

在对象字面量中的例子:

type Rectangle = {
readonly height: number;
readonly width: number;
};


const square: Rectangle = { height: 1, width: 2 };
square.height = 5 // Cannot assign to 'height' because it is a read-only property

值得注意的是,readonly修饰符纯粹是一个typescript结构,当TS被编译到JS时,该结构不会出现在编译后的JS中。当我们修改属性是只读的TS编译器会警告我们(这是有效的JS)。

对我来说,之前的答案都没用。我确实需要将静态类转换为enum。 这样的:< / p >

export enum MyConstants {
MyFirstConstant = 'MyFirstConstant',
MySecondConstant = 'MySecondConstant'
}

然后在我的组件中,我添加了其他答案中建议的新属性

export class MyComponent {
public MY_CONTANTS = MyConstans;
constructor() { }
}

然后在我的组件模板中,我这样使用它

<div [myDirective]="MY_CONTANTS.MyFirstConstant"> </div>

编辑:对不起。我的问题和OP的不同。如果别人有和我一样的问题,我还是会把它留在这里。

所有带有readonly的回复只适用于纯TS环境——如果它曾经被做成一个库,那么这实际上不会阻止任何事情,它只是为TS编译器本身提供警告。

静态也是不正确的——这是向类添加方法,而不是类的实例——所以你需要直接寻址它。

有几种方法可以管理这个,但是纯TS的方法是使用getter—就像您已经做的那样。

另一种方法是把它放在readonly中,但然后使用Object.defineProperty来锁定它-这几乎是通过getter完成的相同的事情,但你可以锁定它有一个值,而不是一个方法来获取它-

class MyClass {
MY_CONSTANT = 10;


constructor() {
Object.defineProperty(this, "MY_CONSTANT", {value: this.MY_CONSTANT});
}
}

默认设置为只读,但请查看文档以了解更多详细信息。

如果你想要封装常量,它不一定是一个类,它可以是一个命名空间,这里有不同的选项:

const MY_CONST_1 = "MyText"

这是最优的选项,并生成以下js:

const MY_CONST_1 = "MyText"

其他选项是封装在命名空间:

namespace Constants {
export const MY_CONST_1: string = 'MyText';
}

这将生成以下js:

var Constants;
(function (Constants) {
Constants.MY_CONST_1 = 'MyText';
})(Constants || (Constants = {}));

和类的其他选项:

abstract class ConstantsClass {
static readonly MY_CONST_1 = "MyText";
}

这将生成以下js:

class ConstantsClass {
}
ConstantsClass.MY_CONST_1 = "MyText";

你可以选择最适合你的。

你也可以简单地在let say中声明:src/classes/Car/consts/Honda.ts

export const CIVIC: string = "Civic";


export default {
CIVIC: CIVIC
};

然后在类文件中执行如下操作:

import Honda from "./consts/Honda";


export class Car {


protected model: string = Honda.Civic;


[...]


}


export default Car;

这样,你就能确保它是一个常数。如果您正在构建数据集,这种方法也非常有用。