565

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

我发现自己需要在代码中明确指出不应更改属性。如果我在声明属性后尝试为其分配新值,我希望 IDE 或编译器出错。你们是如何做到这一点的?

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

get MY_CONSTANT():number {return 10};

我正在使用打字稿 1.8。建议?

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

4

8 回答 8

867

TypeScript 2.0 有readonly修饰符

class MyClass {
    readonly myReadOnlyProperty = 1;

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

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

它不完全是一个常量,因为它允许在构造函数中赋值,但这很可能没什么大不了的。

替代解决方案

另一种方法是使用static关键字 with 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

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

于 2016-05-17T00:59:25.640 回答
88

常量可以在类之外声明并在您的类中使用。否则,该get属性是一个很好的解决方法

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}
于 2016-05-17T00:51:34.940 回答
71

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

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

@see TypeScript Deep Dive book - 只读

于 2017-07-06T14:07:59.117 回答
14

Angular 2 提供了一个非常好的特性,称为不透明常量。创建一个类并使用不透明的常量在那里定义所有常量。

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/"    
};

将其注入 app.module.ts 中的提供程序

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

编辑 Angular 4:

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

注入令牌在不透明令牌之上添加功能,它允许通过 TypeScript 泛型在令牌上附加类型信息,加上注入令牌,无需添加 @Inject

示例代码

Angular 2 使用不透明令牌

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 中不推荐使用不透明令牌。

于 2017-01-19T14:07:05.680 回答
9

仅当这是一个纯 TS 环境时,所有回复readonly才适用 - 如果它曾经被制作成一个库,那么这实际上并不能阻止任何事情,它只是为 TS 编译器本身提供警告。

静态也不正确 - 那是向类添加方法,而不是类的实例- 所以你需要直接解决它。

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

另一种方法是将它放入 as readonly,然后使用Object.defineProperty它来锁定它 - 这几乎与通过 getter 完成的事情相同,但您可以将其锁定为具有值,而不是用于获取它的方法-

class MyClass {
    MY_CONSTANT = 10;

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

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

于 2020-08-09T13:16:55.947 回答
4

要么将 readOnly 修饰符与需要声明的常量一起使用,要么可以在类外部声明一个常量,并仅在使用 get 运算符的所需类中专门使用它。

于 2017-08-18T04:41:28.997 回答
4

为此,您可以使用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修饰符纯粹是一个打字稿构造,当 TS 编译为 JS 时,该构造将不会出现在编译的 JS 中。当我们修改只读属性时,TS 编译器会警告我们(它是有效的 JS)。

于 2019-07-10T17:10:20.290 回答
-2

对我来说,早期的答案都不起作用。我确实需要将我的静态类转换为枚举。像这样:

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

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

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

然后在我的组件模板中我以这种方式使用它

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

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

于 2020-02-18T08:22:33.667 回答