2021년 2월 6일 토요일

[Typescript/Nodejs] global에 함수를 추가하기.2

global에 함수 추가하기1 처럼 global에 함수를 추가할 수도 있지만, 함수 앞에 클래스명 또는 interface 이름을 붙여서 사용하고 싶기도 하다.

전역으로 함수를 만들어서 쓸 경우, 이 모듈을 누가 불러다 쓸 때 이름이 중복되거나 비슷해서 문제가 생길 수 있기 때문이다.

d.ts에 다음과 같이 선언한다.

1
2
3
4
5
6
7
interface __type {
    _isNumber(source: any): boolean;
    _isString(source: any): boolean;
    _isArray(source: any): boolean;
}
 
declare var _type: __type;
cs

interface로 하나의 타입을 선언하고 그 타입의 변수를 만든다. 여기서 중요한건 var인데, var의 특성 때문에 동작하는 것으로 보인다.

구현부에서는 다음과 같이 한다.

1
2
3
global._type._isArray = function (source) {
    return compare(source, Array);
}
cs

사용은 다음과 같이 한다.

1
_type.isArray([]);
cs

하지만 이렇게 할 경우 d.ts에 var로 선언을 해야한다는 단점이 있다.(const, let으로 하면 에러남) var는 javascript에서 사용을 자제하고 있기 때문이다.

이것을 피하려면 두 가지 방법이 있는데....

첫 번째는 global 객체에 namespace, interface 선언 병합을 이용하는 방법이 있다. 

global 객체의 구현부를 보면 아래와 같이 되어 있다.

declare var global: NodeJS.Global & typeof globalThis;

앗...var로 선언되어 있네;; 선언할 때 var를 사용해도 크게 문제가 없는건가....아무튼

위의 d.ts에서 var를 const로 변경한다.

1
2
3
4
5
6
7
interface __type {
    _isNumber(source: any): boolean;
    _isString(source: any): boolean;
    _isArray(source: any): boolean;
}
 
declare const _type: __type;
cs

그리고 구현부에서 아래의 코드를 추가해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
declare global {
    namespace NodeJS {
        interface Global {
            _type: __type
        }
    }
}
 
export = () => {
    global._type._isArray = function (source) {
        return compare(source, Array);
    }
}    //type.ts. 함수를 export
cs

declare global {} 은 같은 파일안에 export 또는 import 구문이 있을 경우에만 사용할 수 있다.(왜인지는 잘 모르겠음...아는 분은 이글을 보신다면 댓글로 설명 좀 부탁드립니다.)

NodeJS는 namespace이고 Global은 interface이다. 그래서 위와 같이 선언해서 에러가 나지 않도록 선언해준다.(선언 병합. namespace와 interface는 선언 병합이 가능하다.)

이렇게 작업 한 후 위 파일을 import해서 사용하면 된다. 사용은 동일하게 한다.

1
2
3
const type = require("type");
type();    //실행해줘야 global에 세팅됨. 함수가 export되어 있는 상태
_type.isArray([]);
cs

두 번째 방법은 Object.defineProperty를 이용해서 global에 값을 세팅하는 것이다.

d.ts는 첫 번째 방법에 나와있는 것과 동일하다.

구현부에서 다음과 같이 한다.

1
2
3
4
5
6
7
8
9
10
11
12
export = () => {
    Object.defineProperty(global, '_type', {
        enumerable: false,
        configurable: false,
        writable: false,
        value: {
            _isArray: function(source: any) {
                return compare(source, Array);
            }
        }
    });
}
cs

Object.defineProperty와 Object.defineProperties가 있다. 후자는 값을 여러개 세팅할 수 있다. 이외의 값들은 Object.defineProperty 를 참고하자.

이렇게 하면 좀 더 깔끔하게 global에 함수를 추가할 수 있다.

댓글 없음: