如何在typescript中实现类常量?

Bee*_*ice 363 class-constants typescript

在TypeScript中,const关键字不能用于声明类属性.这样做会导致编译器出错,"类成员不能拥有'const'关键字."

我发现自己需要在代码中清楚地指出不应该更改属性.如果我在声明属性后尝试为该属性分配新值,我希望IDE或编译器出错.你们是如何实现这一目标的?

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

get MY_CONSTANT():number {return 10};
Run Code Online (Sandbox Code Playgroud)

我正在使用typescript 1.8.建议?

PS:我现在正在使用打字稿2.0.3,所以我接受了大卫的回答

Dav*_*ret 560

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
Run Code Online (Sandbox Code Playgroud)

它不是一个常量,因为它允许在构造函数中赋值,但这是一个简单的选项.

替代方案

另一种方法是使用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
Run Code Online (Sandbox Code Playgroud)

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

  • 要从类外部访问属性,您需要在`class`之前添加`export`关键字以及在`readonly`关键字之前添加`public static`.见这里:http://stackoverflow.com/a/22993349 (26认同)
  • `export`(外部模块)和 `public` 关键字与这个问题/答案无关,但在明确性的话题上,我个人发现当关键字不存在时,很容易判断成员是公共的。由于这个原因,我不理会它,因为它会增加更多的噪音并且是不必要的打字。它还使公共成员与标记为“私有”或“受保护”的成员更加不同。无论如何,只是我的意见:) (2认同)

j3f*_*3ff 59

常量可以在类之外声明并在类中使用.否则该get物业是一个很好的解决方法

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 角度样式指南,而不是TypeScript样式指南.问题是关于TypeScript的 (10认同)
  • 谢谢; 我担心这个实现,因为它不可移植(在模型中,常量实际上不是类的一部分)并且它将信息泄漏到更大的范围,但它具有成为一个真正常数的优点,所以我赢了'能够改变它而不会发出警钟. (6认同)
  • @Esko我相信在打字稿中const仅限于文件,因为每个文件都是一个模块。为了使其可以在外部访问,您需要使用“export const”声明它,然后从另一个文件导入它。不过测试起来很容易。只需在一个文件中声明一个“const”,然后尝试在另一个文件中使用它而不需要导出/导入,或者从浏览器控制台使用它。 (4认同)
  • 根据https://angular.io/docs/ts/latest/guide/style-guide.html,请使用camel caase而不是大写.不推荐使用大写的大写字母. (3认同)
  • 我理解这种担忧,并且我发现使用“get”属性非常适合您的情况 (2认同)

am0*_*0wa 31

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

export class MyClass {
  public static readonly MY_PUBLIC_CONSTANT = 10;
  private static readonly myPrivateConstant = 5;
}
Run Code Online (Sandbox Code Playgroud)

@see TypeScript Deep Dive book - Readonly


Par*_*iya 9

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/"    
};
Run Code Online (Sandbox Code Playgroud)

在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
    ]
  }
]
Run Code Online (Sandbox Code Playgroud)

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!
    ]
  }
]
Run Code Online (Sandbox Code Playgroud)

注射标记在逻辑上设计在不透明标记之上,而不透明标记在Angular 4中已弃用.

  • 加一.Angular和13岁的少年一样稳定.它们在发布后几个月就被弃用了.小气. (6认同)
  • 减一。这个问题与Angular无关。它正在请求 TypeScript 解决方案。 (3认同)

Wil*_*een 6

为此,您可以使用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.
Run Code Online (Sandbox Code Playgroud)

对象文字中的示例:

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
Run Code Online (Sandbox Code Playgroud)

还值得知道的是,readonly修饰符纯粹是一个打字稿构造,当 TS 编译为 JS 时,该构造将不会出现在编译后的 JS 中。当我们修改只读属性时,TS 编译器会警告我们(这是有效的 JS)。


Ryc*_*het 6

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

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

有几种方法可以解决这个问题,但纯 TS 方法是使用 a getter- 正如您已经完成的那样。

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

class MyClass {
    MY_CONSTANT = 10;

    constructor() {
        Object.defineProperty(this, "MY_CONSTANT", {value: this.MY_CONSTANT});
    }
}
Run Code Online (Sandbox Code Playgroud)

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