๐ TypeScript ์์ ์ฐ๊ด๋ ํ์ ์ ์ํ๊ธฐ
TypeScript
๋ฅผ ์ด์ฉํด์ ๊ฐ๋ฐ์ ํ๋ค๋ณด๋ฉด ์๋ก ์ฐ๊ด๋ ๊ฐ์ ํ์
์ผ๋ก ์ ์ํ ๋
enum
ํน์ union type
์ ์ด์ฉํด์ ์ ์ํ๊ฒ ๋ฉ๋๋ค.
๋๊ฐ์ง ๋ฐฉ๋ฒ ์ค์์ ์ด๋ค๊ฒ์ด ์ต์ ์ธ์ง ํญ์ ๊ณ ๋ฏผ์ด ๋์๋๋ฐ
์ด๋ฒ ๊ธฐํ์ ๋์ ์ฐจ์ด์ ์ ๋ํด์ ์์๋๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ์ ๋ฆฌํด๋ดค์ต๋๋ค.
๋ง์ฝ ๋๋ฐ์ด์ค์ ์ข
๋ฅ์ ๋ํ ํ์
์ string union
์ผ๋ก ์ ์ํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
type DeviceType = "phone" | "desktop" | "pad" | "watch"
์ด๋ฅผ enum
์ ์ด์ฉํด์ ํ์
์ ์ ์ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
enum DeviceType {
phone = 'phone',
desktop = 'desktop',
tablet = 'tablet',
watch = 'watch'
}
๋ ์ข ๋ฅ์ ๋ฐฉ์์ผ๋ก ํ์ ์ ์ ์ํ ์ ์๋๋ฐ..
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๊ฒฝ์ฐ์ ์ด ๋ ๋ฐฉ๋ฒ์ค์์ ํ๋๋ฅผ ์ ํํ ์ ์์๊น์?
๐ enum ์ ๋ฌธ์ ์
๋จผ์ enum
์ ์ฌ์ฉํ ๋ ์ด๋ค ์ ์ฝ์ฌํญ์ด ์กด์ฌํ๋์ง ์์๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ์ด๋ค ๊ฒฝ์ฐ์ enum
์ ์ฌ์ฉํด์ผํ ์ง ๊ฒฐ์ ํ๋๋ฐ ๋์์ด ๋์ง ์์๊น์?
1๏ธโฃ enum ํ์ฅํ์ฌ ํ์ ์ ์ํ๊ธฐ
enum
์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฅ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
๊ทธ ๋๋ฌธ์ ๋ง์ฝ ํน์ enum
๊ณผ ๋ค๋ฅธ enum
์ ํฉ์ณ ๋ค๋ฅธ enum
์ ๋ง๋ค๊ธฐ ์ํด์๋
๋ค์๊ณผ ๊ฐ์ด union type
์ ์ด์ฉํด์ผํฉ๋๋ค.
enum Fruit {
APPLE,
BANANA
}
enum AnotherFruit {
PINEAPPLE,
GRAPE,
}
type Fruits = Fruit | AnotherFruit
const fruit: Fruit = Fruit.APPLE
2๏ธโฃ enum ์ ๋ํ import ํ์์ฑ
enum
์ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด value
์ ํด๋นํ๋ ๊ฐ์ ์ง์ ํ ๋นํ ์ ์์ต๋๋ค.
๋์ ํด๋นํ๋ enum
์ ์ฌ์ฉํ๋ ์ชฝ์์ ๋ถ๋ฌ์ ํ ๋นํด์ผํฉ๋๋ค.
๋ง์ฝ union type
์ ์ฌ์ฉํ๋ค๋ฉด IDE ์๋์์ฑ ๊ธฐ๋ฅ์ ์ด์ฉํด ์๋ฆฌํ๊ฒ ํ์
์ ์ถ๋ก ํ ์ ์์ด
๊ฐ๋์ฉ์ ์ด๋ฌํ ๋ฐฉ์์ด ๋ฒ๊ฑฐ๋กญ๋ค๊ณ ๋๊ปด์ง๋ ๊ฒฝ์ฐ๊ฐ ์์์ต๋๋ค.
/**
* ๋ง์ฝ ๋ค์๊ณผ ๊ฐ์ด Fruit ์ด๋ enum ์ด ์ ์๋์ด์๊ณ
*/
enum Fruit {
APPLE = 'APPLE',
BANANA = 'BANANA'
}
/**
* ๋ค๋ฅธ ํ์ผ์์ ์ด enum ์ ์ธ์๋ก ๋ฐ๋ ํจ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด
*/
getSomeFruits('APPLE') // โ
getSomeFruits(Fruit.APPLE) // โ
3๏ธโฃ enum ์ ๋ถ์์ ํ ํ์ ์์ ์ฑ
enum
์ค์์ numeric enum
์ ํ์
์์ ์ฑ์ ๋ณด์ฅํด์ฃผ์ง ์์ต๋๋ค.
์ด๋ numeric enum
์ ํ์ฉํด์ flag
๊ฐ์ ์ ์ํ๊ณ
bitwise
์ฐ์ฐ์ ํตํด ๊ฐ์ ๋ค๋ฃจ๋ ๊ฒ์ ๊ณ ๋ คํ ์ค๊ณ๋ฐฉ์์ ๊ธฐ์ธํ ๋์์
๋๋ค.
Github ์์ TypeScript
repository ์ ๊ด๋ จ ์ด์๋ฅผ ์ดํด๋ณด๋ฉด ํด๋น ๋ฐฉ์์ ๋ํ ๊ทผ๊ฑฐ๋ฅผ ์ง์ด์ฃผ๊ณ ์์ต๋๋ค.
@from DanielRosenwasser
The behavior is motivated by bitwise operations.
There are times when Flag.Foo | Flag.Bar
is intended to produce another Flag
.
Instead you end up with number, and you don't want to have to cast back to
Flag.
enum Status {
pending = 0,
success = 1,
fail = 2
}
const newStatus: Status = 100 // ์๋ฌ๊ฐ ๋ฐ์ ์ํจ!
์์ ๊ฐ์ด Status
๋ฅผ ์ ์ํ์ ๋, 0, 1, 2
๋ง ํ ๋น ๊ฐ๋ฅํด์ผ ํ ๊ฒ ๊ฐ์ง๋ง
์๋ํ์ง ์์ ๊ฐ์ธ 100
์ ํ ๋นํด๋ ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์์ด ์ปดํ์ผ ๋๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ numeric enum
์ ์ฌ์ฉํ ๋๋ ์ฃผ์๊ฐ ํ์ํฉ๋๋ค.
4๏ธโฃ ์ฝ๋ ์ฌ์ด์ฆ ์ฆ๊ฐ
enum
์ ๊ฒฐ๊ตญ JavaScript
๊ฐ์ฒด๋ก ์ปดํ์ผ๋๊ธฐ ๋๋ฌธ์ ๋ง์ enum
์ ์ธ์
์ ์ฒด์ ์ธ ์ฝ๋ ์ฌ์ด์ฆ์ ์ํฅ์ ์ค ์๋ ์์ต๋๋ค.
์ด๋ ๋ฐ๋ก ๋ค์ ์ฑํฐ์์ ์ค์ ๋ฒ๋ค๋ง ์ฌ์ด์ฆ ๋น๊ต๋ฅผ ํตํด ์์๋ณด๊ฒ ์ต๋๋ค.
๐ ๋ฒ๋ค๋ง๋ ์ฝ๋ ์ฌ์ด์ฆ ๋น๊ตํ๊ธฐ
์ค์ ๋ฒ๋ค๋ง๋๋ ์ฝ๋ ์ฌ์ด์ฆ๋ฅผ ํ์ธํ๊ธฐ ์ํด์ webpack + typescript
ํ๊ฒฝ์ ๊ตฌ์ฑํ๊ณ
DeviceType
์ ์ด์ฉํด ๊ฐ๋จํ ํ
์คํธ๋ฅผ ์งํํ์ต๋๋ค.
1๏ธโฃ enum
/** โ
example.ts ์ ๋ค์๊ณผ ๊ฐ์ ํ์
์ด ์ ์๋์ด์๊ณ */
export enum DeviceType {
phone = "phone",
desktop = "desktop",
tablet = "tablet",
watch = "watch",
}
/** โ
index.ts ์์ ์ด๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค๋ฉด? */
import { DeviceType } from "./example";
const device: DeviceType = DeviceType.desktop;
/** โ
๋ค์๊ณผ ๊ฐ์ด bundle.js ๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค! */
/***/ "./src/example.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
exports.DeviceType = void 0;
var DeviceType;
(function (DeviceType) {
DeviceType["phone"] = "phone";
DeviceType["desktop"] = "desktop";
DeviceType["tablet"] = "tablet";
DeviceType["watch"] = "watch";
})(DeviceType = exports.DeviceType || (exports.DeviceType = {}));
/***/ }),
/***/ "./src/index.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var example_1 = __webpack_require__(/*! ./example */ "./src/example.ts");
var device = example_1.DeviceType.desktop;
2๏ธโฃ const enum
/** โ
example.ts ์ ๋ค์๊ณผ ๊ฐ์ ํ์
์ด ์ ์๋์ด์๊ณ */
export const enum DeviceType {
phone = "phone",
desktop = "desktop",
tablet = "tablet",
watch = "watch",
}
/** โ
index.ts ์์ ์ด๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค๋ฉด? */
import { DeviceType } from "./example";
const device: DeviceType = DeviceType.desktop;
/** โ
๋ค์๊ณผ ๊ฐ์ด bundle.js ๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค! */
/***/ "./src/index.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var device = "desktop" /* desktop */;
/***/ })
3๏ธโฃ const object
๋ค์๊ณผ ๊ฐ์ด Device
์ ๋ํ ํ์
์ const object
๋ก ์ ์ํ๋ค๋ฉด,
/** โ
example.ts ์ ๋ค์๊ณผ ๊ฐ์ ํ์
์ด ์ ์๋์ด์๊ณ */
export const Device = {
phone: "phone",
desktop: "desktop",
tablet: "tablet",
watch: "watch",
} as const;
export type DeviceType = typeof Device[keyof typeof Device];
/** โ
index.ts ์์ ์ด๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค๋ฉด? */
import { Device, DeviceType } from "./example";
const device: DeviceType = Device.desktop;
/** โ
๋ค์๊ณผ ๊ฐ์ด bundle.js ๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค! */
/***/ "./src/example.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
exports.Device = void 0;
exports.Device = {
phone: "phone",
desktop: "desktop",
tablet: "tablet",
watch: "watch",
};
/***/ }),
/***/ "./src/index.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var example_1 = __webpack_require__(/*! ./example */ "./src/example.ts");
var device = example_1.Device.desktop;
/***/ })
4๏ธโฃ union type
/** โ
example.ts ์ ๋ค์๊ณผ ๊ฐ์ ํ์
์ด ์ ์๋์ด์๊ณ */
export type DeviceType = "phone" | "desktop" | "tablet" | "watch";
/** โ
index.ts ์์ ์ด๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค๋ฉด? */
import { DeviceType } from "./example";
const device: DeviceType = "desktop";
/** โ
๋ค์๊ณผ ๊ฐ์ด bundle.js ๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค! */
/***/ "./src/index.ts":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var device = "desktop";
/***/ })
5๏ธโฃ ์ข ํฉํด๋ณด๋ฉด..
์ ๋ฒ๋ค๋ง ๊ฒฐ๊ณผ๋ฅผ ์ข ํฉํด๋ณด๋ฉด,
union type
< const enum
< const object
< enum
์์ผ๋ก ์ฝ๋ ์ฌ์ด์ฆ๊ฐ ์ฆ๊ฐํ๋ฉฐ
ํ์ ์ด ๋ง์์ง ์๋ก ์ ์ฒด ์ฝ๋ ๋ฒ๋ค๋ง ์ฌ์ด์ฆ์ ์ํฅ์ ์ค ์ ์์ ๊ฒ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค.
๐ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ enum ์ ๋์ฒด ๊ฐ๋ฅํฉ๋๋ค
1๏ธโฃ union type ์ฌ์ฉํ๊ธฐ
string enum
์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด union type
์ผ๋ก ๋ณ๊ฒฝํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
๋ ํ์ ์ ๊ธฐ๋ฅ์ด ๋์ผํ์ง๋ ์์ง๋ง ์ธ ๊ฐ์ง ์ํ๋ฅผ ์ ์ํ๋ ๋ชฉ์ ์์ ๋์ผํ ์ญํ ์ ์ํํฉ๋๋ค.
numeric enum
์ ์์ ๋งํ ์ด์ ๋ค ๋๋ฌธ์ ํน์ํ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ ๋ ์ฌ์ฉ์ ์ง์ํ๋ฏ๋ก
๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ ๋ํด์๋ union type
์ผ๋ก ์ ์ ๊ฐ๋ฅํฉ๋๋ค.
enum Permission {
READ = 'READ',
WRITE = 'WRITE',
EXECUTE = 'EXECUTE'
}
type Permission = 'READ' | 'WRITE' | 'EXECUTE'
2๏ธโฃ const object ์ฌ์ฉํ๊ธฐ
ํ์
์คํฌ๋ฆฝํธ ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด, ๋ชจ๋ ํ์
์คํฌ๋ฆฝํธ์์๋ enum
์ ์ฌ์ฉํ๋ ๋์
๊ฐ์ฒด๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๊ถ์ฅํ๊ณ ์์ต๋๋ค.
const Device = {
phone: 'phone',
desktop: 'desktop',
tablet: 'tablet',
watch: 'watch'
} as const
// type DeviceType = "phone" | "desktop" | "tablet" | "watch"
type DeviceType = typeof Device[keyof typeof Device]
๐ enum ์ฌ์ฉ์ ์ ํํ๋ eslint ๊ท์น
eslint
์ no-restricted-syntax
๊ท์น์ ์ด์ฉํ๋ฉด enum
์ฌ์ฉ์ ์ ํํ ์ ์์ต๋๋ค.
๋ง์ฝ ํ ๋ด์์ enum
์ฌ์ฉ์ ์ ํํ๋๋ก ๊ฒฐ์ ํ๋ค๋ฉด ๊ณ ๋ คํด๋ณผ๋งํ ๋ฐฉ๋ฒ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
{
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "TSEnumDeclaration",
"message": "โ do not use enum"
}
]
}
}
๐ ๊ทธ๋ ๋ค๋ฉด ์ธ์ enum ์ ์ฌ์ฉํด์ผ ํ ๊น?
๋๋ถ๋ถ์ ๊ฒฝ์ฐ enum
์ ์ ๋ ๋ฐฉ๋ฒ์ ํตํด ๋์ฒด ๊ฐ๋ฅํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๊ฒฝ์ฐ์ enum
์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์๊น์?
๋ฆฌ๋ฒ์ค ๋งคํ (reverse mapping)
enum
์ ํน๋ณํ ์ ์ numeric enum
์ ๋ํด์ reverse mapping
์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์
๋๋ค.
// ๋ค์๊ณผ ๊ฐ์ enum ์
enum Animal {
DOG,
CAT,
}
// ์๋์ ๊ฐ์ด ์ปดํ์ผ๋ฉ๋๋ค
var Animal;
(function (Animal) {
Animal[Animal["DOG"] = 0] = "DOG";
Animal[Animal["CAT"] = 1] = "CAT";
})(Animal || (Animal = {}));
์ฌ๊ธฐ์ Animal['DOG'] = 0
๊ณผ ๋์์ ๋ฐ๋๋ก Animal[0] = 'DOG'
๋ฅผ ํ ๋นํ๋ ๊ฒ์
reverse mapping
์ด๋ผ๊ณ ํฉ๋๋ค.
reverse mapping
์ enum
๋ง์ ํน์ง์ด๋ผ๊ณ ํ ์ ์์ง๋ง..
์ฌ์ค reverse mapping
์ด ํ์ํ ๊ฒฝ์ฐ๊ฐ ์ค์ ๋ก ๋ง์๊น? ํ๋ ์๊ฐ์
๋๋ค.
๋ฐํ์์ ํ์ ์ ์ ๊ทผํด์ ๊ฐ์ ์ฝ์ด์ค๋ ๊ฒ์ด ๊ณผ์ฐ ์ข์ ์ค๊ณ๊ฐ ๋ง์์ง,
๊ทธ๋ฆฌ๊ณ ์ค๋ น ๋ฐ๋์ ๊ทธ๋ฐ ๊ฒฝ์ฐ๊ฐ ํ์ํ๋๋ผ๋ ์ด๋ฅผ enum
์ด ์๋๋ผ ๋ณ๋์ ๊ฐ์ฒด๋ก ์ ์ํด์
์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ด ๋ง์ง ์์๊น? ๋ผ๋ ๊ณ ๋ฏผ์ด ๋ญ๋๋ค. ๐ค
โ ๏ธ numeric enum ์ฌ์ฉ ์ ์ฃผ์์ฌํญ
๊ทธ๋ฆฌ๊ณ numeric enum
์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํ ๋นํ์ง ์์ผ๋ฉด
0
๋ถํฐ ํ๋์ฉ ์ฆ๊ฐํ ๊ฐ์ด ์๋์ผ๋ก ํ ๋น๋ฉ๋๋ค.
์ด ๋๋ฌธ์ ์ถํ์ ํ๋์ ์ ์ธ ์์๋ฅผ ๋ณ๊ฒฝํ๊ฒ๋๋ฉด ๊ฐ์ด ๋ฌ๋ผ์ง ์ ์์ต๋๋ค.
enum Animal {
DOG, // DOG = 0
CAT, // CAT = 1
}
// versus.
enum Animal {
CAT, // CAT = 0
DOG, // DOG = 1
}
๊ทธ ๋๋ฌธ์ ์์ ํ ์ฝ๋ฉ์ ์ํด ๋ช ์์ ์ผ๋ก ์ ์๊ฐ์ ๋ถ์ฌํ๋ ๊ฒ์ ์ ํธํ๋๋ฐ,
Flag
๊ฐ์ ์ด์ฉํ๋ ํ์
์ ์ ์ํ๋ ๊ฒ์ด ์๋๋ผ๋ฉด ๊ทธ๋ฅ string enum
์ ์ฌ์ฉํ๋ ๊ฒ์ด
๋ ์ง๊ด์ ์ด๊ณ ์์ ํ ๋ฐฉ๋ฒ์ด ์๋๊น? ํ๋๊ฒ ์ ์ ๊ฐ์ธ์ ์ธ ์๊ฒฌ์ ๋๋ค. ๐ค
๐ ๊ทธ๋์ ๊ฒฐ๋ก ์?
TypeScript
๋ฅผ ์ฌ์ฉํ๋ ์
์ฅ์์ ํ์
์ ์ธ์ ๋ํ ์ผ์ ํ ๊ท์น์ด ์์ผ๋ฉด ์ข๊ฒ ๋ค๊ณ ์๊ฐํด
์์์ ์ ๋ฆฌํ ๋ด์ฉ๋ค๊ณผ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ ์๊ฒฌ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๊ฒฐ๋ก ์ ๋ด๋ ธ์ต๋๋ค.
- ์ฐ์
union type
์ผ๋ก ํ์ ์ ์ ์ํฉ๋๋ค. - ๋ง์ฝ ๋ฐํ์์ ์ ๊ทผ์ด ํ์ํ๋ค๋ฉด
const object
๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ๋ฆฌ๋ฒ์ค ๋งคํ ๋ฑ ํน๋ณํ ๊ฒฝ์ฐ์ ํํ์ฌ
enum
์ ์ฌ์ฉํฉ๋๋ค.
๐ ์ฐธ๊ณ ์๋ฃ
Union Types vs. Enums in TypeScript
The Difference Between TypeScript Unions, Enums, and Objects
Typescript has unions, so are enums redundant?
'๐จโ๐ป web.dev > js.ts' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
async function ์๋ณํ๊ธฐ (1) | 2022.08.08 |
---|---|
[JavaScript] Debounce ์ Throttle ์ ๋ํด ์์๋ณด์ (0) | 2022.07.09 |
[JavaScript] Array.sort ๋ ์์ ์ฑ์ ๋ณด์ฅํ ๊น? (0) | 2022.03.09 |
[TypeScript] js.map ํ์ผ์ ๋ฌด์์ผ๊น? (0) | 2022.03.07 |
[JavaScript] Object.defineProperty ์ ๋ํด์ (0) | 2022.03.06 |
๐ฌ ๋๊ธ