들어가며
타입스크립트의 가장 큰 장점은 강력한 타입 시스템입니다. 타입 시스템은 코드에서 데이터의 형태를 명시적으로 정의하고, 잘못된 데이터나 로직으로 인한 오류를 사전에 방지합니다. 이번 글에서는 타입 추론, 명시적 타입 선언, 유니온 타입과 인터섹션 타입, 타입 별칭 등을 사용하여 타입스크립트의 기본 원리를 이해하고, 실용적인 예제를 통해 실습해봅니다.
1. 타입 추론(Type Inference)과 명시적 타입 선언
1-1. 타입 추론
타입스크립트는 대부분의 경우 변수의 타입을 자동으로 추론합니다.
[typescript]
let message = 'Hello, TypeScript!'; // 타입 추론: string
let age = 25; // 타입 추론: number
위 예제에서 message는 자동으로 string 타입으로 추론됩니다. 별도로 타입을 지정하지 않아도 안전하게 사용할 수 있습니다.
1-2. 명시적 타입 선언
명시적으로 타입을 지정할 수 있으며, 복잡한 데이터 구조일수록 명시적 타입 지정이 중요합니다.
[typescript]
let username: string = 'Alice';
let isLoggedIn: boolean = true;
명시적 타입 선언은 협업 시 코드의 의도를 명확히 전달하는 데 유용합니다.
2. 유니온 타입(Union)과 인터섹션 타입(Intersection)
2-1. 유니온 타입
유니온 타입은 하나 이상의 타입을 허용합니다. | 연산자를 사용하여 정의합니다.
[typescript]
let id: string | number;
id = '1234'; // 가능
id = 5678; // 가능
유니온 타입을 사용하면 다양한 데이터 입력을 처리할 수 있지만, 타입 검사를 통해 안전성을 유지해야 합니다.
[typescript]
function printId(id: string | number): void {
if (typeof id === 'string') {
console.log(`ID (문자열): ${id.toUpperCase()}`);
} else {
console.log(`ID (숫자): ${id.toFixed(2)}`);
}
}
2-2. 인터섹션 타입
인터섹션 타입은 여러 타입의 속성을 모두 포함합니다. & 연산자를 사용합니다.
[typescript]
interface User {
name: string;
}
interface Admin {
permissions: string[];
}
type AdminUser = User & Admin;
const admin: AdminUser = {
name: 'Alice',
permissions: ['read', 'write'],
};
인터섹션 타입은 두 개 이상의 타입을 결합하여 복합적인 데이터 구조를 표현할 때 유용합니다.
3. 타입 별칭(Type Alias)
3-1. 기본 타입 별칭
타입 별칭은 type 키워드를 사용하여 복잡한 타입을 간단하게 정의할 수 있습니다.
[typescript]
type UserID = string | number;
let id: UserID;
id = 'abc123'; // 가능
id = 456; // 가능
3-2. 객체와 배열의 타입 별칭
복잡한 객체나 배열 타입에도 별칭을 사용할 수 있습니다.
[typescript]
type User = {
id: number;
name: string;
email?: string; // 선택적 속성
};
const user: User = {
id: 1,
name: 'Bob',
};
위 예제에서 email 속성은 선택적(optional) 속성입니다. 타입스크립트는 이를 통해 유연한 데이터 구조를 지원합니다.
4. Null, Undefined 다루기 및 엄격 모드(Strict Mode)
4-1. Null과 Undefined
타입스크립트는 null과 undefined를 명시적으로 처리합니다.
[typescript]
let value: string | null = null;
value = 'Hello';
4-2. 엄격 모드(Strict Mode)
tsconfig.json에서 "strict": true로 설정하면 null이나 undefined와 관련된 잠재적 오류를 사전에 방지할 수 있습니다.
[typescript]
function greet(name: string | null): void {
if (name === null) {
console.log('Hello, Guest!');
} else {
console.log(`Hello, ${name}!`);
}
}
5. any, unknown, never 타입의 활용 및 주의사항
5-1. any 타입
any는 모든 타입을 허용하지만, 타입 검사를 하지 않기 때문에 최대한 사용을 지양해야 합니다.
[typescript]
let value: any = 123;
value = 'Hello'; // 허용
5-2. unknown 타입
unknown은 any와 비슷하지만, 타입 검사를 강제하여 안전성을 제공합니다.
[typescript]
let value: unknown = 'Hello';
if (typeof value === 'string') {
console.log(value.toUpperCase()); // 타입 검사 후 안전하게 사용 가능
}
5-3. never 타입
never는 절대 발생하지 않는 값을 나타내며, 함수가 값을 반환하지 않음을 명시할 때 사용됩니다.
[typescript]
function error(message: string): never {
throw new Error(message);
}
예제: 복잡한 데이터 구조에서 타입 시스템 적용
문제
회사 직원 데이터를 관리하는 프로그램을 작성한다고 가정합니다. 직원은 일반 직원과 관리자 두 가지 유형이 있으며, 관리자만 permissions 속성을 가집니다.
코드
[typescript]
type Employee = {
id: number;
name: string;
department: string;
};
type Manager = Employee & {
permissions: string[];
};
const employees: (Employee | Manager)[] = [
{ id: 1, name: 'Alice', department: 'HR' },
{ id: 2, name: 'Bob', department: 'IT', permissions: ['read', 'write'] },
];
function printEmployeeInfo(employee: Employee | Manager): void {
console.log(`${employee.name} (${employee.department})`);
if ('permissions' in employee) {
console.log(`Permissions: ${employee.permissions.join(', ')}`);
}
}
employees.forEach(printEmployeeInfo);
마무리
이번 글에서는 타입스크립트의 타입 시스템과 관련된 다양한 개념과 활용 방법을 살펴보았습니다. 타입스크립트의 강력한 타입 시스템은 안전한 코드 작성을 가능하게 하며, 특히 대규모 프로젝트에서 협업과 유지보수를 크게 향상시킵니다. 다음 단계에서는 '인터페이스와 클래스'를 학습하여 객체지향 패턴을 더 깊이 이해해보겠습니다.
'프로그래밍 > Typescript' 카테고리의 다른 글
[Typescript] 고급 타입 : 제네릭, 매핑 타입, 조건부 타입 (0) | 2024.12.21 |
---|---|
[Typescript] 인터페이스와 클래스 : 구조적 타이핑과 객체지향 패턴 (1) | 2024.12.20 |
[Typescript] 타입스크립트 기초 입문 : 타입스크립트를 시작하기 위한 첫걸음 (2) | 2024.12.15 |