*튜플(Tuple)**은 타입스크립트에서 길이와 각 요소의 타입이 고정된 배열을 의미합니다. 즉, 미리 정해진 순서대로 다양한 타입의 값을 가질 수 있는 특별한 배열 형태라고 생각하면 됩니다.
왜 튜플을 사용할까요?
- 명확한 데이터 구조 표현: 각 요소의 타입을 명시적으로 지정하여 코드 가독성을 높이고, 예상치 못한 오류를 방지할 수 있습니다.
- 함수 인자 및 반환값 정의: 함수의 입력 값과 출력 값의 형태를 정확하게 지정하여 함수의 동작을 명확히 하고, 타입 안전성을 높일 수 있습니다.
튜플 사용 예시
// 튜플 선언
let person: [string, number] = ['Alice', 30]; // 이름(문자열), 나이(숫자)
// 튜플 요소 접근
console.log(person[0]); // Alice
console.log(person[1]); // 30
// 튜플 타입 사용
function greet(person: [string, number]) {
console.log(`Hello, ${person[0]}! You are ${person[1]} years old.`);
}
greet(['Bob', 25]); // Hello, Bob! You are 25 years old.
다양한 튜플 예시
- 좌표: [number, number]
- 색상: [number, number, number] (RGB 값)
- 사용자 정보: [string, number, boolean] (이름, 나이, 활성 상태)
- 함수 반환값: [number, string] (값, 오류 메시지)
튜플의 장점
- 타입 안전성: 잘못된 타입의 값을 할당하려고 하면 컴파일 시 오류가 발생합니다.
- 코드 가독성 향상: 변수의 의미를 명확하게 나타낼 수 있습니다.
- 함수의 입력 및 출력 값 제한: 함수의 동작을 예측 가능하게 만들어줍니다.
튜플의 단점
- 유연성 부족: 요소의 개수나 타입을 변경하기 어렵습니다.
- 복잡한 데이터 구조 표현에는 한계가 있을 수 있습니다.
더 자세한 예시
// 튜플 안에 튜플
let address: [string, [number, number]] = ['Seoul', [123, 456]];
// 튜플과 rest 파라미터
function sum(...numbers: [number, ...number[]]) {
return numbers.reduce((total, n) => total + n, 0);
}
// 제네릭과 튜플
interface Tuple<T, U> {
0: T;
1: U;
}
let myTuple: Tuple<string, number> = ['hello', 42];
다양한 선언 방식과 활용
튜플 타입은 타입스크립트에서 데이터의 구조를 명확하게 정의하고, 코드의 안정성을 높이는 데 유용한 도구입니다. 앞서 기본적인 튜플 선언 방식을 살펴보았고, 이번에는 좀 더 다양하고 심화된 튜플 선언 방식과 활용 예시를 살펴보겠습니다.
1. 읽기 전용 튜플 (Readonly Tuple)
튜플의 값을 변경할 수 없도록 만들어 데이터의 무결성을 보장할 수 있습니다.
let readonlyTuple: readonly [string, number] = ['Alice', 30];
// readonlyTuple[0] = 'Bob'; // 에러: 읽기 전용이므로 값 변경 불가
2. 옵셔널 요소 (Optional Element)
튜플의 마지막 요소에만 ?를 붙여 옵셔널로 만들 수 있습니다.
let optionalTuple: [string, number?] = ['Alice', 30];
optionalTuple = ['Bob']; // 두 번째 요소는 생략 가능
3. Rest 파라미터와 함께 사용
튜플의 마지막 요소를 rest 파라미터로 지정하여 가변적인 길이의 튜플을 만들 수 있습니다.
let restTuple: [string, ...number[]] = ['Alice', 1, 2, 3];
4. 제네릭과 함께 사용
튜플의 요소 타입을 일반화하여 재사용성을 높일 수 있습니다.
interface Tuple<T, U> {
0: T;
1: U;
}
let genericTuple: Tuple<string, number> = ['hello', 42];
5. 인터페이스와 함께 사용
튜플을 인터페이스의 속성으로 사용하여 더 복잡한 데이터 구조를 표현할 수 있습니다.
interface Person {
name: string;
age: number;
address: [string, number]; // 튜플을 속성으로 사용
}
6. 튜플 타입 가드
typeof 연산자를 사용하여 값이 특정 튜플 타입인지 확인할 수 있습니다.
function isPersonTuple(obj: any): obj is [string, number, boolean] {
return Array.isArray(obj) && obj.length === 3 && typeof obj[0] === 'string' && typeof obj[1] === 'number' && typeof obj[2] === 'boolean';
}
7. 스프레드 연산자와 함께 사용
튜플을 다른 배열에 펼쳐서 사용할 수 있습니다.
let arr1 = [1, 2];
let arr2: [string, ...number[]] = ['hello', ...arr1];
튜플 활용 예시
- 함수의 인자와 반환값: 함수의 입력 값과 출력 값의 형태를 정확하게 지정하여 함수의 동작을 명확히 하고, 타입 안전성을 높일 수 있습니다.
- 객체의 속성: 객체의 속성을 튜플로 표현하여 데이터 구조를 명확하게 정의할 수 있습니다.
- React 컴포넌트의 props: 컴포넌트의 props를 튜플로 정의하여 props의 타입을 강제하고, 오류를 줄일 수 있습니다.
더 다양한 선언 방식과 활용
앞서 튜플 타입의 다양한 선언 방식과 활용 예시를 살펴보았습니다. 이번에는 좀 더 심화된 내용과 실제 개발에서 자주 사용되는 패턴들을 중심으로 튜플 타입을 다루어 보겠습니다.
1. 인덱스 시그니처와 함께 사용
튜플의 요소에 접근할 때 인덱스 시그니처를 사용하여 더 유연하게 타입을 지정할 수 있습니다.
interface NamedTuple {
[index: number]: string;
}
let names: NamedTuple = ['Alice', 'Bob', 'Charlie'];
2. 조건부 타입과 함께 사용
조건부 타입을 활용하여 튜플의 요소에 대한 더 복잡한 타입 검사를 수행할 수 있습니다.
type IsStringArray<T> = T extends (string | number)[] ? T extends string[] ? true : false : false;
type StringTuple = IsStringArray<typeof names> extends true ? typeof names : never;
3. 맵드 타입과 함께 사용
맵드 타입을 사용하여 튜플의 모든 요소에 동일한 변환을 적용할 수 있습니다.
type ReadonlyTuple<T> = ReadonlyArray<T>;
type ReadonlyStringTuple = ReadonlyTuple<string>;
4. 튜플 유틸리티 타입
자주 사용되는 튜플 관련 작업을 위한 유틸리티 타입을 만들어 사용할 수 있습니다.
type TupleToObject<T extends readonly any[]> = {
[K in keyof T]: T[K];
};
5. 튜플과 제네릭의 조합
튜플과 제네릭을 함께 사용하여 더욱 강력하고 재사용 가능한 타입을 만들 수 있습니다.
type TupleToObject<T extends readonly any[]> = {
[K in keyof T]: T[K];
};
function mapTuple<T extends readonly any[], U>(
tuple: T,
mapper: (value: T[number], index: number) => U
): U[] {
return tuple.map(mapper);
}
6. 실제 개발에서의 활용 예시
- React 컴포넌트 props: 컴포넌트의 props를 튜플로 정의하여 props의 타입을 강제하고, 오류를 줄일 수 있습니다.
- Redux action creators: 액션 생성 함수의 인자와 반환값을 튜플로 정의하여 액션의 형태를 명확하게 하고, 타입 안전성을 높일 수 있습니다.
- API 응답 데이터 모델링: API에서 받아오는 데이터의 구조를 튜플로 모델링하여 데이터 처리를 용이하게 할 수 있습니다.
'웹개발 > typescript' 카테고리의 다른 글
[타입스크립트] 숫자 타입 (0) | 2024.08.30 |
---|---|
[타입스크립트] 객체 타입 (0) | 2024.08.30 |
[타입스크립트] 함수 타입 (0) | 2024.08.30 |
[타입스크립트] any 타입 / unknown 타입 (0) | 2024.08.30 |
[타입스크립트] 배열 타입 (2) | 2024.08.30 |