리터럴 타입(Literal Type)이란?
TypeScript 리터럴 타입은 특정한 값만을 허용하는 타입으로, string
, number
, boolean
의 구체적인 값을 타입으로 지정할 수 있습니다. 예를 들어, 문자열 `"yes"`만 허용하거나 숫자 1
만 허용하는 타입을 만들 수 있습니다.
let answer: "yes" | "no"; answer = "yes"; // OK answer = "no"; // OK // answer = "maybe"; // Error: '"maybe"'는 허용되지 않음
리터럴 타입은 함수나 객체의 입력 값을 정확하게 제한하고자 할 때 유용합니다.
리터럴 타입과 유니온 타입 결합
리터럴 타입은 유니온 타입과 함께 사용하면, 허용 가능한 값의 범위를 명확히 지정할 수 있습니다.
type Direction = "up" | "down" | "left" | "right"; function move(dir: Direction) { console.log(`Moving ${dir}`); } move("up"); // OK move("left"); // OK // move("back"); // Error
이처럼 Direction
타입은 제한된 문자열 값만을 허용하여 오타나 잘못된 입력을 방지할 수 있습니다.
리터럴 타입을 활용한 타입 좁히기
TypeScript에서는 리터럴 타입을 이용해 타입 좁히기(Type Narrowing)를 할 수 있으며, 조건문과 함께 사용하면 안전한 분기 처리가 가능합니다.
function getIcon(type: "info" | "warning" | "error") { if (type === "info") { return "ℹ️"; } else if (type === "warning") { return "⚠️"; } else { return "❌"; } }
이 방식은 TypeScript가 각 분기 내에서 타입을 자동으로 좁혀주기 때문에, 런타임 오류를 줄이고 안전한 코드를 작성할 수 있게 도와줍니다.
튜플(Tuple)이란 무엇인가?
TypeScript 튜플(Tuple)은 고정된 수의 요소를 가지는 배열로, 각 요소의 타입이 지정되어 있습니다. 일반 배열과 달리 요소마다 다른 타입을 지정할 수 있어 구조화된 데이터를 표현하기에 적합합니다.
let userInfo: [string, number]; userInfo = ["Alice", 25]; // OK // userInfo = [25, "Alice"]; // Error: 순서 및 타입 불일치
튜플은 구조가 명확하고 정해진 위치에 특정 타입의 값이 들어가야 할 때 유용하게 사용됩니다.
튜플의 구조 분해(Destructuring)
튜플은 배열처럼 구조 분해 할당을 사용할 수 있으며, 각 위치의 타입이 고정되어 있어 코드의 명확성과 안정성을 높입니다.
const point: [number, number] = [10, 20]; const [x, y] = point; console.log(`X: ${x}, Y: ${y}`);
튜플의 각 요소는 명확한 타입을 갖고 있으므로, 변수 x
와 y
도 각각 number
타입으로 추론됩니다.
튜플에 리터럴 타입 적용하기
리터럴 타입과 튜플을 함께 사용하면, 더 강력한 타입 제어가 가능합니다. 특히 이벤트, 파라미터 명세, 커맨드 처리 등의 로직에 적합합니다.
type Command = ["start", number] | ["stop", string]; function handleCommand(cmd: Command) { if (cmd[0] === "start") { console.log(`Starting with ID: ${cmd[1]}`); } else { console.log(`Stopping: ${cmd[1]}`); } } handleCommand(["start", 123]); // OK handleCommand(["stop", "done"]); // OK // handleCommand(["start", "oops"]); // Error
위 예제는 튜플의 첫 번째 요소로 명령어를, 두 번째 요소로 데이터를 받는 형식을 정해 명확한 데이터 구조를 제공합니다.
튜플의 확장 (Rest 요소)
TypeScript 4.0 이후부터는 튜플에 Rest 요소를 사용할 수 있어, 일부 요소만 고정하고 나머지는 유동적으로 처리할 수 있습니다.
type Log = [string, ...number[]]; const log1: Log = ["데이터", 1, 2, 3]; const log2: Log = ["이벤트"]; // 숫자 없이도 OK
이 기능은 고정된 앞부분과 가변적인 뒷부분을 갖는 데이터 구조에 유용하게 사용됩니다.
실무에서의 활용 사례
- API 응답에서 고정된 순서의 데이터 처리
- 상태 전이(state transition) 정의
- 이벤트 핸들러에서 커맨드 패턴 구현
- 파라미터의 순서와 타입이 중요한 함수 설계
튜플과 리터럴 타입은 사용자가 정의한 구조를 명확하게 표현하고, 예상치 못한 입력을 방지할 수 있도록 돕습니다.
결론: 정밀한 타입 제어를 위한 리터럴과 튜플의 활용
TypeScript의 리터럴 타입은 값 자체를 타입으로 제한할 수 있는 기능이며, 튜플은 고정된 형태의 데이터를 명확히 표현할 수 있는 타입입니다. 두 기능은 실무에서 데이터 모델을 세밀하게 정의하고, 예측 가능한 코드를 작성하는 데 큰 도움이 됩니다.
정확한 타입 제어가 필요한 상황에서 이 두 가지 기능을 적절히 활용한다면, 코드의 안정성은 물론, 유지보수성과 가독성도 크게 향상될 것입니다.