[TypeScript] as const는 무엇일까

Sara Jo·2025년 2월 2일

TypeScript에서 as const (const assertion) 는 특정 값이 변경되지 않음을 TypeScript에게 알려주는 역할을 한다. 이를 사용하면 TypeScript가 해당값을 가능한 가장 좁은 타입(narrow type)으로 추론하게 되는데, 이게 도대체 무슨 말인지 차근차근 알아보자.


as const 의 기본동작

일반적으로 변수를 선언하면 TypeScript는 해당 변수를 보다 넓은 타입으로 추론한다.

let foo = 'foo';
// let foo: string

하지만 as const를 추가하면, TypeScript는 이 값을 리터럴 타입(literal type)으로 고정한다.

let foo = 'foo' as const;
// let foo: 'foo'

숫자의 경우도 마찬가지이다.

let num = 10 as const;
// let num: 10

const와 as const의 차이

그러면 const 키워드와 똑같은 것 아닌가? 라고 생각이 들지만 둘은 객체나 배열에 사용할 때 큰 차이가 있다.

const obj = { key: 'value' };
// const obj: { key: string }

let obj2 = { key: 'value' } as const;
// let obj: { readonly key: 'value' }

as const를 사용하면 객체의 속성이 읽기 전용(readonly)이 되어 값을 변경할 수 없다.

obj2.key = 'new value';
// 오류: 'key'는 읽기 전용 속성입니다.

객체와 배열에서의 as const

객체에서의 as const

객체에 as const를 적용하면 모든 속성이 readonly가 되며, 각 속성의 타입이 리터럴 값으로 고정된다.

const myObject = {
    name: 'Alice',
    age: 25,
} as const;

// const myObject: { readonly name: 'Alice'; readonly age: 25; }

myObject.age = 30; // 오류 발생 (읽기 전용 속성)

배열에서의 as const

배열에 as const를 적용하면 튜플(tuple)처럼 동작하며, 각 요소의 타입이 리터럴로 고정된다.

튜플이란, 배열과 비슷하지만 요소의 개수와 타입이 고정된 자료구조이다. as const를 사용하면 배열의 요소가 변경되지 않으며, 순서까지 보장된다.

const colors = ['red', 'green', 'blue'] as const;

// const colors: readonly ['red', 'green', 'blue']

colors[0] = 'yellow'; // 오류 발생 (읽기 전용 배열)
colors.push('yellow'); // 오류 발생 (push 사용 불가)

as const의 활용 예시

유니온 타입과 as const

as const는 유니온 타입을 생성할 때 유용하게 사용할 수 있다.

type ButtonVariant = 'primary' | 'secondary' | 'danger';

const buttonVariants = ['primary', 'secondary', 'danger'] as const;

// 배열을 `as const`로 선언하면 각 요소가 리터럴 타입으로 고정됨
// 따라서 `typeof buttonVariants[number]`를 사용하면 각 요소의 타입을 추출하여 유니온 타입을 만들 수 있음
type ButtonVariantFromArray = typeof buttonVariants[number];
// 'primary' | 'secondary' | 'danger'

이와 같이 buttonVariants 배열에 as const를 적용하면, ButtonVariant라는 타입을 별도로 정의하지 않아도 buttonVariants 배열에서 자동으로 유니온 타입을 생성할 수 있다.

React의 useState와 as const

ReactuseState를 사용할 때 as const를 사용하면 더 정확한 타입 추론이 가능하다.

function useToggle() {
    const [isActive, setIsActive] = useState(false);
    const toggle = () => setIsActive(prev => !prev);
    return [isActive, toggle] as const;
}

const [isActive, toggle] = useToggle();
// isActive: boolean
// toggle: () => void

as const가 없으면 useToggle의 반환값이 (boolean | (() => void))[]으로 추론된다. 즉, 배열 요소의 순서나 타입이 정확하게 유지되지 않는다.

하지만 as const를 사용하면 튜플 타입이 유지되어 반환된 값의 순서와 타입이 정확하게 보장된다. 즉, isActive는 항상 boolean, toggle은 항상 () => void 타입을 가지므로 타입 안정성이 더욱 높아진다.


결론

TypeScript의 as const변수의 값을 변경할 수 없도록 고정하면서, 타입을 가능한 가장 좁은 범위로 제한하는 기능이다. 특히 객체와 배열을 읽기 전용으로 만들거나, 유니온 타입을 생성할 때 유용하다.

정리하면, 아래와 같은 경우에 as const를 적절히 활용하면 안전한 코드 작성과 타입 안정성을 높일 수 있다!

  1. 객체나 배열을 변경 불가능하게 만들고 싶을 때
  2. 리터럴 타입을 활용하여 더 정확한 타입 추론이 필요할 때
  3. 유니온 타입을 자동으로 생성할 때
  4. ReactuseState와 같은 훅을 사용할 때 튜플 형태로 반환값을 보장하고 싶을 때

[참고]
https://www.omarileon.me/blog/typescript-as-const

0개의 댓글