enum 보다 union type을 사용하자
Feb 4, 2022
union type을 사용하는게 좋은 이유
enum을 쓰는 경우
// fruit.ts
export enum Fruit {
Apple = 'Apple',
Orange = 'Orange',
Grape = 'Grape',
}
// import_enum.ts
import { Fruit } from './fruit';
const fruit: Fruit = Fruit.Apple;
console.log(fruit);
이를 tsc로 트랜스파일링 후 rollup으로 번들링하면 아래와 같이 변환된다.
var Fruit;
(function (Fruit) {
Fruit['Apple'] = 'Apple';
Fruit['Orange'] = 'Orange';
Fruit['Grape'] = 'Grape';
})(Fruit || (Fruit = {}));
var fruit = Fruit.Apple;
console.log(fruit);
union type을 쓰는 경우
// fruit.ts
export type Fruit = 'Apple' | 'Orange' | 'Grape';
// import_union.ts
import { Fruit } from './fruit';
const fruit: Fruit = 'Apple';
console.log(fruit);
이를 트랜스파일링 및 번들링 하면 아래와 같다.
var fruit = 'Apple';
console.log(fruit);
union type을 쓰는 경우 장점
- js로 변환시 코드가 줄어든다. enum은 js로 트랜스파일링 될때 타입과는 달리 사라지지 않기 때문에 코드양을 증가시킨다.
- enum과 달리 import를 하지 않아도 사용할 수 있다. (컴포넌트의 props 등에 지정되어 있을때)
- enum보다 선언 방법이 간단하다.
ts↦type Fruit = 'Apple' | 'Orange' | 'Grape'
- union type을 사용해도 ide (e.g. vscode)의 auto complete 기능이 활성화된다.
같이 보면 좋은 tsconfig.json
옵션
esModuleInterop
(default: false)
이 옵션이 false
또는 not set
이라면 CommonJS/AMD/UMD 모듈을 ESM처럼 취급한다.
문제가 되는 경우는 아래처럼 CJS 모듈을 ESM 코드베이스로 가져오려고 할 때다.
// node_modules/moment/index.js
exports = moment;
// app/index.ts
import * as moment from 'moment';
moment(); // moment는 순수 객체만 될 수 있어서 이렇게 사용하는 것은 ESM 스펙을 준수하지 않음!
// 트랜스파일링된 결과
const moment = require('moment');
moment();
esModuleInterop
를 활성화하면 ESM 사양에 따라 CJS 모듈을 가져올 수 있다.
// app/index.ts
import moment from 'moment';
moment(); // ESM 스펙을 준수함
// 트랜스파일링된 결과
const moment = __importDefault(require('moment'));
moment.default();
isolatedModules
(default: false)
Babel이나 다른 빌드툴은 한번에 하나의 하나의 파일에서만 작동하므로 const enum
이나 namespace
같은 타입스크립트 기능을 사용하는데 런타임 문제가 발생할 수 있다. 이 옵션을 true
로 설정하면 단일 파일 변환 프로세스에서 올바르게 해석할 수 없는 코드를 작성할 경우 경고를 받게 된다.
대표적으로 모든 실행 파일들은 모듈이어야 한다는 규칙이 있다.
importsNotUsedAsValues
(default: remove)
import가 어떻게 처리되는지를 결정하는 플래그이다.
- remove : 참조 타입만 drop
- preserve : 사용되지 않는 값이나 타입들도 전부 보존한다. side-effects를 일으킬 수도 있음
- error : 모든 import를 보존하지만, value import가 값처럼 사용되면 error을 출력
preserveValueImports
(default: false)
타입스크립트가 import를 사용하고 있음을 감지하지 못하는 경우가 있다. Svelte나 Vue처럼 Compiles to HTML 언어를 사용하거나 아래와 같은 경우다.
import { Animal } from './animal.js';
// eval에서 Animal을 사용하지만 string이므로 인식하지 못한다
eval('console.log(new Animal().isDangerous())');
isolatedModules
옵션과 함께 사용되는 경우, import 된 타입은 컴파일러가 이 import 가 사용되지 않는 값인지 또는 삭제되어야 하는 type 인지 알 수 없기 때문에 type-only
로 지정해야 한다.
// ts 4.5부터 modifier를 붙일 수 있음
import { TitleComponent, type TitleComponentProps } from './TitleComponent.js';