2025 . 오은

repo

as const

문제 정의

TypeScript를 사용하여 개발하면서, 특정 값들의 집합을 타입으로 정의하고 동시에 데이터로도 활용해야 하는 상황이 자주 발생했습니다. 예를 들어, 포켓몬의 능력(abilities)을 정의할 때 단순한 문자열 배열로 선언하면, 해당 배열을 타입으로 활용하기 어렵다는 문제가 있었습니다. 리터럴 타입으로만 정의할 경우, 데이터로는 유연하게 사용할 수 없고, 타입으로만 제한적으로 사용할 수 있었습니다.

const abilities = [
    "air-lock", "arena-trap", "battle-armor",
    // 기타 등등...
];

위와 같이 단순히 배열로 선언하면, abilities 배열의 각 요소를 타입으로 활용할 때 리터럴 타입으로 인식되지 않아 타입 안전성이 떨어지고, 코드의 유연성이 제한되는 문제가 있었습니다.

해결 과정

이 문제를 해결하기 위해 const Assertion을 도입하게 되었습니다. const Assertion을 사용하면, 배열이나 객체를 읽기 전용으로 만들 뿐만 아니라, 각 요소의 리터럴 타입을 고정시킬 수 있습니다. 이를 통해 데이터로도 활용하면서 동시에 타입으로도 사용할 수 있는 구조를 만들 수 있게 되었습니다.

1. const Assertion 도입 const Assertion을 사용하여 배열을 선언하면, 배열의 각 요소가 리터럴 타입으로 고정되고, 배열 자체도 읽기 전용으로 변환됩니다.

const abilities = [
    "air-lock", "arena-trap", "battle-armor",
    // 기타 등등...
] as const;

위와 같이 as const를 추가함으로써, abilities 배열은 변경 불가능한(readonly) 튜플로 변환되며, 각 요소는 해당 리터럴 타입으로 고정됩니다.

2. 리터럴 타입을 통한 타입 정의 const Assertion을 통해 생성된 배열을 기반으로 타입을 정의함으로써, 배열의 각 요소를 타입으로 활용할 수 있게 되었습니다.

export type PokemonAbilityTypes = typeof abilities[number];

위 코드에서 PokemonAbilityTypes는 abilities 배열의 각 요소를 타입으로 추출한 유니언 타입("air-lock" | "arena-trap" | "battle-armor" | ...)이 됩니다. 이를 통해 포켓몬의 능력을 타입으로 안전하게 사용할 수 있게 되었습니다.

3. 타입과 데이터의 동시 활용 이제 abilities 배열을 데이터로 사용할 뿐만 아니라, PokemonAbilityTypes 타입을 통해 타입 안전성을 확보할 수 있게 되었습니다.

const myAbility: PokemonAbilityTypes = "air-lock"; // 올바른 값
const invalidAbility: PokemonAbilityTypes = "fly"; // 오류 발생

myAbility는 PokemonAbilityTypes에 정의된 유효한 값만 할당할 수 있어, 잘못된 값 할당 시 컴파일 타임에 오류를 방지할 수 있습니다.

결과

const Assertion을 도입한 후 다음과 같은 개선 효과를 얻었습니다:

  • 타입 안전성 강화: 배열의 각 요소가 리터럴 타입으로 고정되어, 잘못된 값의 할당을 컴파일 타임에 방지할 수 있었습니다.
  • 코드의 가독성 및 유지보수성 향상: 데이터와 타입을 동시에 관리할 수 있어, 코드의 일관성과 가독성이 크게 향상되었습니다.
  • 유연한 데이터 활용: 배열을 데이터로 자유롭게 사용할 수 있으면서도, 타입으로는 엄격하게 제한할 수 있어 코드의 유연성과 안전성을 모두 확보할 수 있었습니다.
  • 불변성 보장: const Assertion을 통해 배열이 읽기 전용으로 변환되어, 의도치 않은 데이터 변경을 방지할 수 있었습니다.

배운 점 (인사이트)

  • as const의 유용성: const Assertion을 통해 데이터와 타입을 동시에 관리할 수 있는 강력한 방법을 학습하게 되었습니다. 이는 특히 리터럴 타입을 기반으로 한 타입 안전성이 중요한 상황에서 매우 유용합니다.
  • 타입과 데이터의 분리 관리: 타입과 데이터를 분리하여 관리하는 대신, 동일한 소스에서 타입과 데이터를 동시에 생성할 수 있는 방법을 이해하게 되었습니다. 이는 코드의 일관성과 유지보수성을 높이는 데 큰 도움이 됩니다.
  • 불변성의 중요성: 데이터를 읽기 전용으로 선언함으로써, 불변성을 유지하고 데이터 변경으로 인한 버그를 사전에 방지할 수 있다는 점을 깨달았습니다.
  • TypeScript의 고급 기능 활용: const Assertion과 같은 TypeScript의 고급 기능을 적절히 활용하여, 코드의 안정성과 효율성을 높일 수 있다는 점을 경험했습니다.