TypeScript 5.8에 --erasableSyntaxOnly라는 컴파일러 플래그가 추가됐다. 이름만 봐선 뭔가 싶은데, Node.js 네이티브 TS 지원, TC39 표준화 움직임과 맞물려 있는 플래그다.
새 플래그가 하는 일
tsconfig.json에 이 옵션을 켜면, 특정 TypeScript 문법을 사용할 때 컴파일 에러가 난다.
{
"compilerOptions": {
"erasableSyntaxOnly": true
}
}
금지되는 것들:
-
enum선언 - 런타임 코드가 있는
namespace - Parameter properties (
constructor(public x: number)) -
import =alias - Old-style type assertion (
<Type>value)
왜 이것들만 콕 집어서 막는 걸까?
"Erasable"이 뭔가
Erasable은 "지울 수 있는"이라는 뜻이다. TypeScript 문법 중에서 그냥 지워버려도 JavaScript 실행에 아무 영향이 없는 것을 erasable하다고 한다.
// ✅ Erasable - 타입만 지우면 됨
function greet(name: string): string {
return `Hello, ${name}`;
}
// 타입 지운 결과
function greet(name) {
return `Hello, ${name}`;
}
반면 enum은 다르다.
// ❌ Non-erasable - 지우면 안 됨
enum Status {
Active,
Inactive
}
console.log(Status.Active); // 0
enum을 그냥 지워버리면? Status가 없어지니까 런타임 에러다. TypeScript 컴파일러가 이걸 JavaScript 객체로 변환해줘야 돌아간다.
// 컴파일 결과
var Status;
(function (Status) {
Status[Status["Active"] = 0] = "Active";
Status[Status["Inactive"] = 1] = "Inactive";
})(Status || (Status = {}));
이게 "erasable하지 않다"의 의미다. 단순히 타입을 지우는 게 아니라 JavaScript 코드를 생성해야 한다.
왜 이게 지금 나왔나
두 가지 움직임 때문이다.
1️⃣ Node.js의 네이티브 TypeScript 지원
Node.js 23.6부터 --experimental-strip-types 플래그로 TypeScript 파일을 직접 실행할 수 있다.
node --experimental-strip-types app.ts
근데 이름에서 알 수 있듯이 "strip types", 타입을 벗겨내기만 한다. enum이나 namespace처럼 JavaScript 변환이 필요한 건 지원 안 한다.
Node.js has unflagged a mode called
--experimental-strip-typeswhich requires that any TypeScript-specific syntax cannot have runtime semantics.
— TypeScript 공식 문서
2️⃣ TC39 "Types as Comments" 제안
더 큰 그림이 있다. TC39(JavaScript 표준을 만드는 곳)에서 "Types as Comments"라는 제안이 Stage 1로 진행 중이다. TypeScript PM인 Daniel Rosenwasser가 직접 champion으로 참여하고 있다.
핵심 아이디어는 브라우저가 TypeScript 타입 문법을 주석처럼 무시하게 만드는 것이다.
// 미래의 JavaScript?
function add(a: number, b: number): number {
return a + b;
}
// 브라우저: "a: number? 몰라, 무시하고 실행할게"
이게 되면 빌드 스텝 없이 TypeScript를 바로 실행할 수 있다. 대신 조건이 있다. 타입은 "무시"할 수 있어야 한다. enum처럼 실제 JavaScript 코드를 만들어내는 문법은 scope 밖이다.
Enums, namespaces, and parameter properties would be out of scope for this proposal since they have observable runtime behavior.
— Daniel Rosenwasser, 2022
그래서 enum은 deprecated인가?
아니다. TypeScript 팀은 enum을 deprecated로 선언한 적 없다.
2020년에 "Deprecate const enum"이라는 GitHub 이슈(#41641)가 올라왔는데, TypeScript 팀이 Declined(거절) 처리했다. 하위 호환성을 깨뜨릴 생각이 없다는 뜻이다.
다만 공식 핸드북에서는 이런 뉘앙스를 준다:
In modern TypeScript, you may not need an enum when an object with
as constcould suffice... The biggest argument in favour of this format over TypeScript's enum is that it keeps your codebase aligned with the state of JavaScript.
"쓰지 마"가 아니라 "JavaScript 방향에 맞추려면 대안 고려해봐"다.
실무에서 어떻게 하면 되나
--erasableSyntaxOnly를 당장 켜야 하는 건 아니다. 기존 코드 다 고쳐야 하니까. 하지만 새 코드에서는 이런 대안을 쓰는 게 미래 지향적이다.
enum → as const
// Before
enum Status {
Active = 'active',
Inactive = 'inactive'
}
// After
const Status = {
Active: 'active',
Inactive: 'inactive'
} as const;
type Status = typeof Status[keyof typeof Status];
namespace → ES modules
// Before
namespace Utils {
export function format(s: string) { ... }
}
// After (utils.ts)
export function format(s: string) { ... }
parameter properties → 명시적 할당
// Before
class User {
constructor(public name: string) {}
}
// After
class User {
name: string;
constructor(name: string) {
this.name = name;
}
}
정리
| 질문 | 답변 |
|---|---|
| enum deprecated? | ❌ 아님 |
| 새 코드에서 권장? | ⚠️ 대안 고려 권장 |
| 제거 계획? | ❌ 없음 (하위 호환성) |
TypeScript 팀은 기존 코드를 깨뜨리지 않으면서, opt-in 플래그로 점진적 전환을 지원하는 전략을 택했다. TypeScript Design Goals 문서를 보면 이 방향성이 처음부터 있었다:
"Align with current and future ECMAScript proposals"
"Encourage programming patterns that do not require run-time metadata"
enum과 namespace는 TypeScript 초창기(2012년)에 만들어졌다. 그때는 JavaScript에 이런 게 없었으니까. 지금은 as const, ES modules 같은 표준 대안이 생겼고, TypeScript는 그쪽으로 무게중심을 옮기고 있다.
"enum은 실수였다"는 커뮤니티 밈과 달리, 실제로는 실용적 공존을 선택한 것으로 보인다. 다만 새로운 non-erasable 문법은 더 이상 추가하지 않겠다는 건 분명해 보인다.
Top comments (0)