TIL

[TIL] 23.03.13 타입스크립트에서 효율적으로 상수 관리하기

SH_Roh 2023. 3. 14. 02:14
반응형

효율적으로 상수 관리하기

타입스크립트에서는 포괄적인 타입(string, number, ...) 외에도 정확한 값을 타입으로 설정하는 것이 가능하다.

let title: 'typescript';
title = 'javascript'; // Type 'javascript' is not assignable to type 'typescript'

 

타입스크립트에서는 컴파일러가 자동으로 타입을 추론하는 기능을 제공한다. let은 변수의 값을 언제든 바꿀 수 있기 때문에 더 포괄적인 타입으로 값을 추론하고, const의 경우는 변경이 불가능하기 때문에 리터럴 타입으로도 추론된다.

let title = 'typescript'; // let title: string
const content = 'typescript; // const content: 'typescript'

 

타입 단언(Type Assertion)을 활용한 상수 관리

let 변수의 경우에도 const처럼 리터럴 타입으로 추론해줄 수 있는데, 그 때 사용하는 것이 as const이다.

let title = 'typescript' as const; // let title: 'typescript'

 

타입 단언을 활용해서 상수를 관리하는 방법에 대해 알아보자.

const Colors = {
  red: '#FF0000',
  blue: '#0000FF',
  green: '#008000'
}

Colors 변수 내부에 추론된 값을 보면 각 속성이 원시 타입으로 추론된다. 이는 const로 객체를 선언했지만, 객체 내부의 값들은 언제든지 바꿀 수 있기 때문이다.

 

이 때 타입 단언을 통해 Colors 내부값의 타입을 리터럴 타입으로 변경할 수 있고, 편리하게 상수를 관리할 수 있다.

const Colors = {
  red: '#FF0000',
  blue: '#0000FF',
  green: '#008000'
} as const

 

enum을 통한 상수 관리

export enum Colors {   
    red="#FF0000",   
    blue="#0000FF",   
    green="#008000", 
}

타입스크립트에서는 enum이라는 객체를 통해 상수를 쉽게 관리할 수 있다.

 

enum은 타입스크립트에서 제공하는 문법을 아래와 같은 특징을 가진다.

  • enum은 js 객체이나, 내부 속성을 임의로 변경 불가
  • enum의 내부 key는 반드시 리터럴 타입(string or number)으로만 사용 가능
  • enum의 속성값도 리터럴 타입(string or number)만 사용 가능

 

enum vs as const

그렇다면 상수 관리에 enum, as const 중에 어떤 것을 쓰는 것이 더 좋을까?

 

enum과 as const는 탄생한 목적 자체가 다르다. enum서로 연관된 상수들을 하나의 네임스페이스로 묶어 추상화하기 위해 도입된 것이다. 이를 통해 코드만 보더라도 의도를 명확히 알 수 있어 가독성을 높일 수 있다.

반면 as const는 타입 단언의 한 종류로써 리터럴 타입의 추론 범위를 줄이고 값의 재할당을 막기 위한 목적으로 만들어졌다.

 

Object(or Array) 리터럴의 as const

let title = 'typescript' as const

as const를 위와 같이 쓸 수도 있지만 그럴 바에는 아예 const로 선언하는 게 좋을 것이다.

 

그렇지만 원시타입이 아닌 Object나 Array 타입이라면 얘기가 달라진다. 이 둘은 참조 타입이기 때문에 const로 선언해도 내부 프로퍼티의 추론 범위가 한정되지도 않고, 값을 변경할 수도 있다.

 

const language = {
  korean: "ko",						// "ko"로 추론, readonly 프로퍼티로 변경
  english: "en",					// "en"로 추론, readonly 프로퍼티로 변경
} as const;

// Error: Cannot assign to 'korean' because it is a read-only property
language.korean = "kkk";
// Error: Cannot assign to 'english' because it is a read-only property.
language.english = "eee";

이럴 때 as const를 사용하면 객체의 모든 프로퍼티들이 readonly로 변경되고, 각 프로퍼티의 타입이 할당된 리터럴 값으로 추론된다.

 

중첩 객체(배열)의 프로퍼티들도 as const를 사용하면 readonly로 변경되고 리터럴 값으로 추론된다.

const obj = {
  a: 10,
  b: [20, 30],
  c: {
    d: {
      e: {
        greeting: "Hello",
      },
    },
  },
} as const;

이렇듯 as const를 사용하면 원시 타입이든 참조 타입이든 값의 재할당을 막기 때문에 의도치않은 변경으로 인한 오류를 없앨 수 있다. 또한, 리터럴 타입의 추론 범위가 리터럴 값 자체로 한정되면서 좀 더 안전하게 코드를 작성할 수 있다.


References

https://blog.toycrane.xyz/typescript에서-효과적으로-상수-관리하기-e926db079f9

https://velog.io/@logqwerty/Enum-vs-as-const

 

반응형