Làm thế nào để thực hiện các hằng lớp trong bản thảo?


429

Trong TypeScript, consttừ khóa không thể được sử dụng để khai báo các thuộc tính lớp. Làm như vậy sẽ khiến trình biên dịch bị lỗi với "Một thành viên lớp không thể có từ khóa 'const'."

Tôi thấy mình cần phải ghi rõ trong mã rằng một tài sản không nên thay đổi. Tôi muốn IDE hoặc trình biên dịch bị lỗi nếu tôi cố gán giá trị mới cho thuộc tính một khi nó đã được khai báo. Làm thế nào để các bạn đạt được điều này?

Tôi hiện đang sử dụng một thuộc tính chỉ đọc, nhưng tôi chưa quen với Bản mô tả (và JavaScript) và tự hỏi liệu có cách nào tốt hơn không:

get MY_CONSTANT():number {return 10};

Tôi đang sử dụng bản in 1.8. Gợi ý?

Tái bút: Hiện tại tôi đang sử dụng bản thảo 2.0.3, vì vậy tôi đã chấp nhận câu trả lời của David

Câu trả lời:


650

TypeScript 2.0 có công cụ readonlysửa đổi :

class MyClass {
    readonly myReadOnlyProperty = 1;

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

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

Nó không chính xác là một hằng số vì nó cho phép gán trong hàm tạo, nhưng rất có thể đó không phải là vấn đề lớn.

Giải pháp thay thế

Một cách khác là sử dụng statictừ khóa với 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

Điều này có lợi ích là không được gán trong hàm tạo và chỉ tồn tại ở một nơi.


31
Để truy cập các thuộc tính từ bên ngoài lớp, bạn sẽ cần thêm exporttừ khóa trước classcũng như public statictrước readonlytừ khóa. Xem tại đây: stackoverflow.com/a/22993349
cbros2008

Câu hỏi. Không biết tại sao bạn cần tên lớp để sử dụng thuộc tính readOnly đó trong chính lớp đó? 'MyClass.myReadonlyProperty'
Saiyaff Farouk

@SaiyaffFarouk Nếu tôi hiểu câu hỏi của bạn, câu trả lời là các thuộc tính tĩnh tồn tại như một phần của lớp, không phải trên một thể hiện của lớp. Vì vậy, bạn truy cập chúng bằng tên lớp không phải là biến chứa thể hiện của lớp.
JeffryHouser

1
export( Các mô-đun bên ngoài) và publictừ khóa không liên quan đến câu hỏi / câu trả lời này, nhưng về chủ đề của nhân chứng, cá nhân tôi thấy rất dễ dàng để nói rằng một thành viên là công khai khi từ khóa không tồn tại. Tôi không bận tâm với nó vì lý do đó và vì nó thêm tiếng ồn & không cần gõ. Nó cũng làm cho các thành viên công cộng khác biệt hơn so với những người được đánh dấu là privatehoặc protected. Dù sao, chỉ là ý kiến ​​của tôi :)
David Sherret

Còn các lớp ẩn danh thì sao? Bất kỳ ý tưởng về cách truy cập static readonly myReadOnlyPropertykhi lớp được khai báo với export default class { ... }? Cố gắng this.myVar, self.myVar, tĩnh, mặc định ... không làm việc ... (EDIT: default.myVar dường như là giải pháp, nhưng tôi nhận được một lỗi type)
Alcalyn

67

Các hằng số có thể được khai báo bên ngoài các lớp và sử dụng trong lớp của bạn. Nếu không, gettài sản là một cách giải quyết tốt đẹp

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}

6
Cảm ơn; Tôi lo lắng về việc triển khai này vì nó không khả dụng (trong mô hình, hằng số không thực sự là một phần của lớp) và nó rò rỉ thông tin vào phạm vi lớn hơn, nhưng nó có lợi thế là một hằng số thực sự nên tôi đã thắng ' t có thể thay đổi nó mà không tăng chuông báo động.
BeetleJuice

1
Tôi hiểu mối quan tâm và tôi thấy việc sử dụng gettài sản rất phù hợp trong trường hợp của bạn
j3ff

3
Per angular.io/docs/ts/latest/guide/style-guide.html vui lòng sử dụng caase lạc đà thay vì chữ hoa. Trường hợp trên cho hằng số không được khuyến khích.
Vadim Kirilchuk

12
Kiểu dáng góc cạnh, không phải là kiểu chữ TypeScript .. Câu hỏi liên quan đến TypeScript cụ thể
VeldMuijz

4
@Esko Tôi tin rằng trong bản in, const được giới hạn trong tệp vì mỗi tệp là một mô-đun. Để làm cho nó có thể truy cập được bên ngoài, bạn cần phải khai báo nó export constvà sau đó nhập nó từ một tệp khác. Sẽ khá dễ dàng để kiểm tra mặc dù. Chỉ cần khai báo một consttrong một tệp và cố gắng sử dụng nó trong một tệp khác mà không xuất / nhập hoặc sử dụng nó từ bảng điều khiển trình duyệt.
BeetleJuice

42

Bạn có thể đánh dấu các thuộc tính bằng công cụ readonlysửa đổi trong khai báo của bạn:

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

@see TypeScript Deep Dive book - Chỉ đọc


11

Angular 2 Cung cấp một tính năng rất hay được gọi là Hằng số mờ. Tạo một lớp & Xác định tất cả các hằng số ở đó bằng cách sử dụng các hằng số mờ.

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

Tiêm nó trong các nhà cung cấp trong app.module.ts

Bạn sẽ có thể sử dụng nó trên tất cả các thành phần.

EDIT cho góc 4:

Đối với Angular 4, khái niệm mới là Token Token & Mã thông báo mờ không được dùng trong Angular 4.

Mã thông báo tiêm Thêm các chức năng trên đầu trang của Mã thông báo mờ, nó cho phép đính kèm thông tin loại trên mã thông qua các tổng quát của TypeScript, cộng với mã thông báo Tiêm, loại bỏ nhu cầu thêm @Inject

Mã ví dụ

Angular 2 Sử dụng Token Opaque

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 Sử dụng Token tiêm

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!
    ]
  }
]

Mã thông báo tiêm được thiết kế hợp lý trên đầu trang của mã thông báo Opaque & mã thông báo mờ được không dùng trong Angular 4.


6
cộng với một. Angular ổn định như một thiếu niên 13 tuổi. họ nhận được các tính năng không dùng nữa sau vài tháng phát hành. nhỏ mọn
Stavm

1
trừ đi một. Câu hỏi này không liên quan gì đến Angular. Nó đang yêu cầu một giải pháp TypeScript.
Ben Nieting

4

Sử dụng công cụ sửa đổi readOnly với hằng số cần khai báo hoặc người ta có thể khai báo một hằng bên ngoài lớp và chỉ sử dụng cụ thể trong lớp được yêu cầu bằng toán tử get.


1

Đối với điều này, bạn có thể sử dụng công cụ readonlysửa đổi. Các thuộc tính đối tượng readonlychỉ có thể được gán trong quá trình khởi tạo đối tượng.

Ví dụ trong các lớp học:

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.

Ví dụ trong các đối tượng bằng chữ:

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

Cũng đáng để biết rằng công cụ readonlysửa đổi hoàn toàn là một cấu trúc bản thảo và khi TS được biên dịch thành JS, cấu trúc đó sẽ không xuất hiện trong JS được biên dịch. Khi chúng tôi sửa đổi các thuộc tính chỉ đọc, trình biên dịch TS sẽ cảnh báo chúng tôi về nó (đó là JS hợp lệ).


-2

Đối với tôi không có câu trả lời trước đó hoạt động. Tôi đã cần phải chuyển đổi lớp tĩnh của tôi thành enum. Như thế này:

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

Sau đó, trong thành phần của tôi, tôi thêm thuộc tính mới như được đề xuất trong các câu trả lời khác

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

Sau đó, trong mẫu thành phần của tôi, tôi sử dụng nó theo cách này

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

EDIT: Xin lỗi. Vấn đề của tôi khác với OP. Tôi vẫn để điều này ở đây nếu ai đó có vấn đề tương tự như tôi.


Sử dụng một enum để lưu các hằng số không phải là một thực hành tốt trong bất kỳ ngôn ngữ nào.
Tăng

Đó là giải pháp tốt nhất cho các giải pháp hiện có. Tôi biết đó là cách enum không nên được sử dụng nhưng với Angular, đó là cách sạch nhất để có các hằng số liên kết.
Janne Harju
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.