기본 타입
타입스크립트를 배우는 가장 중요한 목적 중 하나는 바로 타입(Type) 을 활용하여 코드의 안정성과 가독성을 높이는 것입니다. 타입은 변수나 함수가 어떤 종류의 데이터를 다룰지 명확하게 정의하는 약속과 같습니다. 마치 우리가 물건을 담을 때 그 물건에 맞는 크기와 재질의 용기를 고르듯이, 코드에서도 데이터의 성격에 맞는 타입을 지정하는 것이죠.
이번 절에서는 타입스크립트에서 가장 기본적으로 제공하는 타입들을 하나씩 살펴보겠습니다. 이 기본 타입들은 여러분이 앞으로 작성하게 될 거의 모든 타입스크립트 코드의 근간이 될 것입니다.
숫자 (Number)
자바스크립트와 마찬가지로 타입스크립트의 숫자(Number) 타입은 정수와 부동소수점 숫자를 모두 포함합니다. 특별히 정수 타입이나 실수 타입이 따로 존재하지 않습니다. 모든 숫자는 64비트 부동소수점 형식으로 저장됩니다.
let decimal: number = 6; // 10진수
let hex: number = 0xf00d; // 16진수
let binary: number = 0b1010; // 2진수
let octal: number = 0o744; // 8진수
let float: number = 10.5; // 부동소수점
console.log(decimal); // 6
console.log(hex); // 61453
console.log(binary); // 10
console.log(octal); // 484
console.log(float); // 10.5
// 오류 예시: 문자열을 숫자에 할당할 수 없습니다.
// let notANumber: number = "hello"; // Type 'string' is not assignable to type 'number'.
위 예시에서 볼 수 있듯이, 다양한 진법의 숫자 리터럴을 number
타입에 할당할 수 있습니다. 중요한 점은 number
타입으로 선언된 변수에는 오직 숫자 값만 할당할 수 있다는 것입니다.
문자열 (String)
문자열(String) 타입은 텍스트 데이터를 나타내는 데 사용됩니다. 자바스크립트와 동일하게 작은따옴표 ('
), 큰따옴표 ("
) 또는 백틱 (`
)을 사용하여 문자열을 정의할 수 있습니다. 백틱으로 정의하는 문자열은 템플릿 리터럴(Template Literals) 이라고 불리며, 여러 줄에 걸쳐 문자열을 작성하거나 표현식을 삽입할 때 유용합니다.
let courseName: string = "TypeScript for Beginners";
let instructor: string = 'Kim Coding';
// 템플릿 리터럴 사용
let introduction: string = `Hello, my name is ${instructor}.
This course is about ${courseName}.`;
console.log(courseName); // TypeScript for Beginners
console.log(introduction);
// Hello, my name is Kim Coding.
// This course is about TypeScript for Beginners.
// 오류 예시: 숫자를 문자열에 할당할 수 없습니다.
// let notAString: string = 123; // Type 'number' is not assignable to type 'string'.
템플릿 리터럴은 문자열 내부에 ${}
구문을 사용하여 변수나 JavaScript 표현식을 삽입할 수 있어, 동적인 문자열을 훨씬 깔끔하게 구성할 수 있도록 돕습니다.
불리언 (Boolean)
불리언(Boolean) 타입은 참(true)
또는 거짓(false)
두 가지 값만을 가질 수 있습니다. 조건문이나 논리 연산에 주로 사용됩니다.
let isCompleted: boolean = false;
let hasError: boolean = true;
if (isCompleted) {
console.log("작업이 완료되었습니다.");
} else {
console.log("작업이 진행 중입니다."); // 이 메시지가 출력됩니다.
}
// 오류 예시: 다른 타입을 불리언에 할당할 수 없습니다.
// let isValid: boolean = 1; // Type 'number' is not assignable to type 'boolean'.
// let isReady: boolean = "yes"; // Type 'string' is not assignable to type 'boolean'.
불리언 타입은 코드의 논리 흐름을 제어하는 데 필수적이며, 타입스크립트 덕분에 true
또는 false
가 아닌 다른 값이 할당되는 실수를 미리 방지할 수 있습니다.
배열 (Array)
배열은 여러 개의 값을 순서대로 저장하는 자료구조입니다. 타입스크립트에서 배열의 타입을 선언하는 방법은 두 가지가 있습니다.
-
요소 타입 뒤에
[]
사용: 가장 흔하게 사용되는 방법입니다. 배열이 포함할 요소들의 타입을 명시하고 그 뒤에 대괄호[]
를 붙입니다.let numbers: number[] = [1, 2, 3, 4, 5]; let fruits: string[] = ["apple", "banana", "cherry"]; // numbers.push("six"); // 오류: 'string' 형식의 인수는 'number' 형식의 매개 변수에 할당될 수 없습니다. console.log(numbers[0]); // 1 console.log(fruits.length); // 3
위 예시처럼
number[]
는 이 배열이 오직 숫자 타입의 요소만을 가질 수 있음을 의미합니다. 다른 타입의 요소를 추가하려 하면 컴파일 시 오류가 발생합니다. -
제네릭 배열 타입 (
Array<ElementType>
): 제네릭 문법을 사용하여Array<요소타입>
형태로 배열 타입을 정의할 수 있습니다. 이는 좀 더 명시적인 방법이며, 제네릭에 익숙해지면 더욱 강력한 타입을 정의할 때 활용됩니다.let numbersGeneric: Array<number> = [10, 20, 30]; let namesGeneric: Array<string> = ["Alice", "Bob", "Charlie"]; console.log(numbersGeneric[1]); // 20
두 방법 모두 동일하게 배열의 타입을 정의하지만, 일반적으로
number[]
와 같은 첫 번째 방식이 더 간결하여 많이 사용됩니다.
튜플 (Tuple)
튜플(Tuple) 은 특정 개수의 요소 타입을 미리 정해놓고, 그 정해진 순서와 타입에 맞춰 값을 담을 수 있는 배열의 한 종류입니다. 배열은 요소의 개수나 타입 순서에 제약이 없지만, 튜플은 정해진 형태를 유지해야 합니다. 고정된 수의 요소와 각 요소의 타입이 중요할 때 유용합니다.
// [string, number]는 첫 번째 요소는 문자열, 두 번째 요소는 숫자여야 함을 의미합니다.
let userInfo: [string, number] = ["John Doe", 30];
let rgbColor: [number, number, number] = [255, 0, 0];
console.log(userInfo[0]); // John Doe
console.log(userInfo[1]); // 30
// 오류 예시: 순서나 타입이 맞지 않습니다.
// let invalidUser: [string, number] = [30, "John Doe"]; // Type 'number' is not assignable to type 'string'.
// let incompleteInfo: [string, number] = ["Jane Doe"]; // Property '1' is missing in type '[string]' but required in type '[string, number]'.
// 요소 추가는 허용되지만, 접근 시 타입 검사가 이루어집니다.
// userInfo.push(true); // 오류는 아니지만, 명확성을 위해 권장되지 않습니다. (튜플은 고정된 길이를 가정)
// userInfo[2]; // Property '2' does not exist on type '[string, number]'.
튜플은 예를 들어 [경도, 위도]
와 같이, 요소의 의미가 순서에 따라 명확하게 구분될 때 빛을 발합니다.
열거 (Enum)
열거(Enum) 는 특정 값들의 집합에 이름을 부여하여, 코드의 가독성을 높이고 오류를 줄이는 데 사용됩니다. 예를 들어, 요일, 색상, 상태 코드 등과 같이 한정된 선택지를 표현할 때 유용합니다. 기본적으로 숫자 값을 가집니다.
// 숫자 열거 (Numeric Enum) - 기본값: 0부터 시작하여 1씩 증가
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
let userDirection: Direction = Direction.Up;
console.log(userDirection); // 0
console.log(Direction.Left); // 2
console.log(Direction[0]); // Up (역방향 매핑도 가능)
// 특정 숫자 값 할당 가능
enum StatusCode {
Success = 200,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404
}
let responseStatus: StatusCode = StatusCode.Success;
console.log(responseStatus); // 200
console.log(StatusCode.NotFound); // 404
// 문자열 열거 (String Enum) - 각 멤버에 문자열 리터럴을 할당해야 합니다.
enum HttpStatus {
OK = "OK",
Created = "CREATED",
InternalServerError = "INTERNAL_SERVER_ERROR"
}
let serverStatus: HttpStatus = HttpStatus.OK;
console.log(serverStatus); // OK
console.log(HttpStatus.InternalServerError); // INTERNAL_SERVER_ERROR
// console.log(HttpStatus[0]); // 문자열 열거는 역방향 매핑을 지원하지 않습니다.
열거형을 사용하면 하드코딩된 숫자나 문자열 대신 의미 있는 이름을 사용할 수 있어 코드가 훨씬 명확해집니다.
Any (아무거나)
any
타입은 타입 검사를 비활성화할 때 사용됩니다. 어떤 종류의 값이든 할당할 수 있으며, any
타입의 변수에 대해 어떤 프로퍼티나 메서드에 접근해도 타입 검사를 하지 않습니다. 이는 자바스크립트의 유연성을 그대로 가져오지만, 타입스크립트를 사용하는 이점을 포기하는 것이므로 꼭 필요한 경우에만 제한적으로 사용해야 합니다.
let unknownValue: any = 4;
unknownValue = "hello";
unknownValue = false;
// any 타입은 어떤 속성이나 메서드에도 접근을 허용합니다.
// 실제 런타임에 오류가 발생할 수 있으니 주의해야 합니다.
unknownValue.toFixed(2); // 숫자일 때는 가능
unknownValue.toUpperCase(); // 문자열일 때는 가능
unknownValue.noSuchMethod(); // 런타임 오류 발생 가능성이 있지만, 컴파일러는 허용합니다.
let someValue: any = "이것은 문자열입니다.";
let strLength: number = (someValue as string).length; // 타입 단언 (as 키워드)
console.log(strLength); // 13
any
는 주로 기존 자바스크립트 라이브러리를 사용할 때, 또는 데이터의 형태를 미리 알 수 없을 때 사용됩니다. 하지만 남용하면 타입스크립트를 사용하는 의미가 퇴색되므로 지양하는 것이 좋습니다.
Void (공허)
void
타입은 주로 함수가 어떤 값도 반환하지 않을 때 사용됩니다. 자바스크립트 함수에서 명시적으로 return
문이 없거나, return;
만 있을 경우 해당 함수의 반환 타입은 void
로 간주됩니다.
function warnUser(): void {
console.log("경고: 이 함수는 어떤 값도 반환하지 않습니다.");
}
let unusable: void = undefined; // void 타입에는 undefined만 할당 가능합니다.
// unusable = null; // strictNullChecks 옵션이 활성화된 경우 오류 (기본적으로는 가능)
warnUser(); // 함수 실행
변수에 void
타입을 직접 할당하는 경우는 거의 없으며, 주로 함수의 반환 타입으로 사용됩니다.
Null과 Undefined
null
과 undefined
는 각각 자신의 이름을 타입으로 가집니다. 이들은 자바스크립트에서 "값이 없음"을 나타내는 특별한 값들입니다.
let u: undefined = undefined;
let n: null = null;
// 기본적으로 null과 undefined는 모든 다른 타입의 하위 타입입니다.
// 즉, number, string 등에 할당될 수 있습니다.
let num: number = undefined; // strictNullChecks가 false일 경우 허용 (기본값)
let str: string = null; // strictNullChecks가 false일 경우 허용
// 하지만 'strictNullChecks' 컴파일 옵션이 true일 경우,
// null과 undefined는 오직 void 또는 자신에게만 할당 가능합니다.
// 이 책에서는 'strictNullChecks: true'를 권장하며, 이는 더 엄격한 타입 검사를 가능하게 합니다.
tsconfig.json
파일에 strictNullChecks: true
옵션을 설정하면 null
과 undefined
가 다른 타입에 할당되는 것을 엄격하게 제한하여 잠재적인 null
참조 오류를 방지할 수 있습니다. 이는 매우 강력한 기능이므로, 이 책에서는 해당 옵션을 활성화하는 것을 권장합니다.
Never (절대)
never
타입은 절대 발생할 수 없는(도달할 수 없는) 타입을 나타냅니다. 주로 다음과 같은 경우에 사용됩니다.
- 함수가 항상 예외를 던지거나(throw),
- 함수가 절대 반환하지 않거나(무한 루프 등),
- 타입 가드(Type Guards)를 사용하여 모든 가능한 경우를 처리했음을 나타낼 때.
// 1. 항상 예외를 던지는 함수
function error(message: string): never {
throw new Error(message);
}
// 2. 무한 루프 함수
function infiniteLoop(): never {
while (true) {
// 이 함수는 절대 종료되지 않습니다.
}
}
// 3. 타입 가드에서 사용
declare function getWidget(): string | number; // 문자열 또는 숫자를 반환하는 가상의 함수
function processWidget(widget: string | number) {
if (typeof widget === "string") {
console.log("위젯은 문자열입니다:", widget.toUpperCase());
} else if (typeof widget === "number") {
console.log("위젯은 숫자입니다:", widget.toFixed(2));
} else {
// 이 코드는 절대 실행될 수 없어야 합니다.
// 만약 widget에 다른 타입이 추가된다면 컴파일러가 오류를 알려줍니다.
let _exhaustiveCheck: never = widget;
}
}
never
타입은 타입스크립트의 타입 시스템에서 특정 코드 경로가 도달 불가능함을 명시적으로 알리는 역할을 합니다.
여기까지 타입스크립트의 가장 기본적인 타입들을 살펴보았습니다. 이 타입들은 여러분이 타입스크립트를 사용하여 견고한 애플리케이션을 구축하는 데 필요한 핵심 빌딩 블록이 될 것입니다. 각 타입의 역할과 사용법을 충분히 익히셨기를 바랍니다.