Programing

TypeScript의 공개 정적 const

lottogame 2020. 5. 25. 08:02
반응형

TypeScript의 공개 정적 const


TypeScript에 공개 정적 상수와 같은 것이 있습니까? 다음과 같은 수업이 있습니다.

export class Library {
  public static BOOK_SHELF_NONE: string = "None";
  public static BOOK_SHELF_FULL: string = "Full";
}

그 수업에서 나는 할 수 Library.BOOK_SHELF_NONE있고 tsc는 불평하지 않습니다. 그러나 클래스 라이브러리를 다른 곳에서 사용하려고하고 동일한 작업을 시도하면 인식하지 못합니다.


이 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은 단순히 내 보낸 함수에 속성으로 연결됩니다. 따라서 함수 자체에 제대로 액세스하는 한 액세스 할 수 있어야합니다.


최신 브라우저에서 정적 상수 값처럼 동작하는 것을 원한다면 (다른 코드로 변경할 수 없음) 클래스에 get유일한 접근자를 추가 할 수 있습니다 Library(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속성을 새 값 으로 설정하려는 시도가 작동하지 않는 것을 볼 수 있습니다.

2.0

TypeScript 2.0에서는 readonly매우 유사한 결과를 얻을 수 있습니다 .

export class Library {
    public static readonly BOOK_SHELF_NONE = "None";
    public static readonly BOOK_SHELF_FULL = "Full";
}

구문은 조금 더 단순하고 분명합니다. 그러나 컴파일러는 런타임이 아닌 변경을 방지합니다 (첫 번째 예와 달리 변경이 시연 된대로 전혀 허용되지 않는 경우).


다음 과 같이 namespaces를 사용하여 수행 할 수 있습니다 .

export namespace Library {
    export const BOOK_SHELF_NONE: string = 'NONE';
}

그런 다음 다른 곳에서 가져올 수 있습니다.

import {Library} from './Library';
console.log(Library.BOOK_SHELF_NONE);

클래스가 필요한 경우 네임 스페이스 안에 클래스를 포함하십시오. export class Book {...}


한편이 조합의 장식을 통해 해결 될 수있다 Object.freeze거나 Object.defineProperty, 내가 이것을 사용하고, 그것은 게터의 톤을 사용하는 것보다 작은 비트 예뻐합니다. TS Playground직접 복사 / 붙여 넣기 하여 실제로 볼 수 있습니다. -두 가지 옵션이 있습니다


개별 필드를 "최종"으로 설정

다음 데코레이터는 주석이 달린 정적 필드와 정적이 아닌 필드를 모두 "getter-only-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
        });
    }
}

As an alternative to the decorator above, there would also be a strict version of this, which would even throw an Error when someone tried to assign some value to the field with "use strict"; being set. (This is only the static part though)

/**
 * 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
    });
}

Make every static field "final"

Possible Downside: This will only work for ALL statics of that class or for none, but cannot be applied to specific statics.

/**
* 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."

Thank you WiredPrairie!

Just to expand on your answer a bit, here is a complete example of defining a constants class.

// CYConstants.ts

class CYConstants {
    public static get NOT_FOUND(): number    { return -1; }
    public static get EMPTY_STRING(): string { return ""; }
}

export = CYConstants;

To use

// main.ts

import CYConstants = require("./CYConstants");

console.log(CYConstants.NOT_FOUND);    // Prints -1
console.log(CYConstants.EMPTY_STRING); // Prints "" (Nothing!)

The following solution also works as of 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"];

To use:

// Main.ts    
import {ReallySafeExtensions, kNotFoundInArray} from "./Constants";

if (ReallySafeExtensions.indexOf("png") === kNotFoundInArray) {
    console.log("PNG's are really unsafe!!!");
}

Just simply 'export' variable and 'import' in your class

export var GOOGLE_API_URL = 'https://www.googleapis.com/admin/directory/v1';

// default err string message
export var errStringMsg = 'Something went wrong';

Now use it as,

import appConstants = require('../core/AppSettings');
console.log(appConstants.errStringMsg);
console.log(appConstants.GOOGLE_API_URL);

You can use a getter, so that your property is going to be reading only. Example:

export class MyClass {
    private _LEVELS = {
        level1: "level1",
        level2: "level2",
        level2: "level2"
    };

    public get STATUSES() {
        return this._LEVELS;
    }
}

Used in another class:

import { MyClass } from "myclasspath";
class AnotherClass {
    private myClass = new MyClass();

    tryLevel() {
       console.log(this.myClass.STATUSES.level1);
    }
}

참고URL : https://stackoverflow.com/questions/22991968/public-static-const-in-typescript

반응형