기본 타입
1. unknown
- 모든 타입의 슈퍼 타입으로, 모든 값이 할당될 수 있습니다.
- 타입이 명확하지 않을 때 사용하지만, any와 달리 제한적입니다. 사용하기 전 명확한 타입으로 좁히는 타입 가드가 필요합니다.
2. any
- 모든 타입을 허용하는 타입으로, 타입 검사를 건너뛰는 역할을 합니다.
- 타입 안정성을 낮출 수 있으므로 가능한 사용을 자제하는 것이 좋습니다.
3. 기본 타입들
- null: null 값만 가질 수 있는 타입입니다.
- void: 함수가 값을 반환하지 않을 때 주로 사용되는 타입입니다.
- number: 숫자 타입이며, Number Enum을 포함합니다.
- bigint: 큰 정수를 표현하는 타입으로, 일반 숫자보다 큰 정수를 다룰 때 사용됩니다.
- boolean: true 또는 false의 불리언 값을 가지는 타입입니다.
- string: 문자열 타입으로, String Enum을 포함합니다.
- symbol: 심볼 타입으로, Unique Symbol을 포함합니다.
- object: 객체 타입을 나타내며, Array, Function, Constructor와 같은 구체적인 타입을 포함합니다.
4. 유형별 세부 타입
- undefined: 정의되지 않은 상태를 나타내며, void나 null 타입과 함께 사용됩니다.
- Number Enum / String Enum: 각각 숫자 또는 문자열 열거형을 나타냅니다.
- Unique Symbol: 고유한 심볼 값을 나타냅니다.
- Array: 배열 타입입니다.
- Function: 함수 타입입니다.
- Constructor: 생성자 함수 타입을 나타냅니다.
5. never
- 절대 도달할 수 없는 값을 의미하는 타입입니다. 보통 오류를 발생시키거나 끝없이 실행되는 함수에 사용됩니다.
- unknown은 모든 타입의 최상위에 위치하며 모든 값을 포함할 수 있습니다.
- any는 unknown 바로 아래에 있으며, 타입 검사를 우회하는 타입입니다.
- 기본 타입들인 null, void, number, bigint, boolean, string, symbol, object가 각각의 하위 타입을 가집니다.
- never는 undefined와 null의 하위 타입으로, 도달할 수 없는 값을 나타냅니다.
# 원시타입과 리터널 타입
- 원시 타입은 기본적인 데이터 타입으로 number, string, boolean 등 JavaScript와 동일한 타입을 포함합니다.
- 리터럴 타입은 고정된 값을 가지도록 제한하는 타입으로, 유니온 타입과 결합하여 특정 값들 중 하나만 가질 수 있도록 할 수 있습니다.
1. 원시 타입 (Primitive Type)
원시 타입은 JavaScript와 TypeScript에서 기본적으로 제공하는 가장 작은 단위의 데이터 타입입니다. 원시 타입은 그 자체로 값을 가지며, 주로 불변(immutable)합니다.
number: 숫자 타입을 나타내며, 정수와 소수를 포함합니다.
let age: number = 30;
string: 문자열 타입을 나타냅니다.
let name: string = "John";
boolean: 불리언 타입으로, true 또는 false 값을 가집니다.
let isStudent: boolean = false;
bigint: 매우 큰 정수를 표현할 수 있는 타입입니다. BigInt 객체를 사용하거나 숫자 뒤에 n을 붙여 선언할 수 있습니다. (ES2020부터 지원)
let largeNumber: bigint = 9007199254740991n;
symbol: 고유한 심볼 값을 가지는 타입입니다. 객체의 고유한 속성 키를 만들 때 유용합니다.
let uniqueKey: symbol = Symbol("key");
undefined: 변수는 선언되었으나 값이 할당되지 않았을 때 기본적으로 가지는 타입입니다.
let notAssigned: undefined = undefined;
null: 값이 없음을 명시적으로 나타내는 타입입니다.
let empty: null = null;
void: 주로 함수에서 반환 값이 없음을 나타낼 때 사용합니다.
function logMessage(): void {
console.log("Hello, TypeScript");
}
never: 절대 도달할 수 없는 값을 나타내는 타입으로, 항상 오류를 발생시키거나 영원히 실행되는 함수에서 사용됩니다.
function throwError(message: string): never {
throw new Error(message);
}
2. 리터럴 타입 (Literal Type)
리터럴 타입은 변수가 가질 수 있는 고정된 값을 특정할 때 사용됩니다. 예를 들어, 문자열 "hello"를 리터럴 타입으로 지정하면, 그 변수는 "hello" 외의 값으로 변경할 수 없습니다. 리터럴 타입은 주로 문자열, 숫자, 불리언 값으로 사용할 수 있으며, 유니온 타입과 결합하여 여러 개의 고정된 값 중 하나만 허용하는 형태로 활용할 수 있습니다.
문자열 리터럴 타입
let direction: "left" | "right" | "up" | "down";
direction = "left"; // 가능
direction = "right"; // 가능
direction = "forward"; // 오류 발생, 지정된 값이 아님
숫자 리터럴 타입
let statusCode: 200 | 404 | 500;
statusCode = 200; // 가능
statusCode = 300; // 오류 발생, 지정된 값이 아님
불리언 리터럴 타입
let isCompleted: true | false;
isCompleted = true; // 가능
isCompleted = false; // 가능
type TrafficLight = "red" | "yellow" | "green";
function getTrafficLightAction(light: TrafficLight) {
switch (light) {
case "red":
return "stop";
case "yellow":
return "slow down";
case "green":
return "go";
}
}
console.log(getTrafficLightAction("red")); // "stop"
# 배열과 튜플
- 배열(Array): 동일한 타입의 값을 여러 개 가질 수 있는 구조. number[] 또는 Array<number> 형태로 선언.
- 튜플(Tuple): 고정된 개수와 타입의 값을 가질 수 있는 구조. [string, number] 형태로 선언.
1. 배열 (Array)
배열은 동일한 타입의 값들을 한 변수에 저장할 수 있는 데이터 구조입니다. JavaScript의 배열과 유사하며, TypeScript에서는 배열에 타입을 지정할 수 있습니다.
배열 선언 방법
대괄호([]) 표기법을 사용하여 배열 타입을 지정
let numbers: number[] = [1, 2, 3, 4, 5];
let fruits: string[] = ["apple", "banana", "orange"];
Array<> 제네릭 표기법을 사용하여 배열 타입을 지정
let numbers: Array<number> = [1, 2, 3, 4, 5];
let fruits: Array<string> = ["apple", "banana", "orange"];
배열의 타입 검사
TypeScript는 배열 요소의 타입을 체크하기 때문에, 배열에 잘못된 타입의 값을 추가하려고 하면 오류가 발생합니다.
let names: string[] = ["Alice", "Bob"];
names.push("Charlie"); // 가능
names.push(123); // 오류 발생, 숫자는 허용되지 않음
2. 튜플 (Tuple)
튜플은 배열과 비슷하지만, 요소의 타입과 길이를 고정할 수 있습니다. 즉, 튜플은 각 요소의 타입과 순서가 미리 결정된 배열입니다. 이를 통해 각 위치에 특정 타입의 값만 저장하도록 강제할 수 있습니다.
튜플은 정해진 위치에 정해진 타입의 값이 들어가야 하는 데이터를 표현할 때 유용합니다.
튜플 선언 방법
튜플은 대괄호([]) 안에 각 요소의 타입을 순서대로 나열하여 선언합니다.
let person: [string, number] = ["Alice", 30];
let person: [string, number] = ["Alice", 30]; // 가능
let person2: [string, number] = [30, "Alice"]; // 오류 발생, 순서가 다름
let person3: [string, number] = ["Alice", "30"]; // 오류 발생, 타입이 다름
예)
function fetchData(): [boolean, string] {
return [true, "Data fetched successfully"];
}
let result = fetchData();
console.log(result[0]); // true
console.log(result[1]); // "Data fetched successfully"
튜플과 배열의 차이점
특징배열(Array)튜플(Tuple)
특징 | 배열(Array) | 튜플(Tuple) |
타입 일관성 | 배열의 모든 요소가 동일한 타입이어야 함 | 요소마다 서로 다른 타입을 가질 수 있음 |
길이 고정 여부 | 길이 제한이 없음 | 길이와 각 요소의 타입이 고정됨 |
사용 목적 | 동일한 타입의 값 집합 | 고정된 구조와 순서가 필요한 데이터 그룹 |
3. 튜플에 선택적 요소와 나머지 요소 지정
TypeScript에서는 튜플에 선택적 요소(?)나 나머지 요소(...)를 사용할 수도 있습니다.
선택적 요소: 특정 요소가 있어도 되고 없어도 되는 경우
let tupleWithOptional: [string, number?] = ["Alice"]; // 가능
tupleWithOptional = ["Alice", 30]; // 가능
나머지 요소: 나머지 요소를 특정 타입의 배열로 받을 수 있음
let tupleWithRest: [string, ...number[]] = ["Alice", 10, 20, 30];
# 객체
- 객체 타입: { 속성: 타입; } 형식으로 객체의 속성 타입을 정의합니다.
- 선택적 속성: 속성 뒤에 ?를 붙여 선택적으로 설정할 수 있습니다.
- 읽기 전용 속성: readonly 키워드로 설정하여 값을 변경하지 못하게 할 수 있습니다.
- 인덱스 시그니처: [key: string]: 타입으로 여러 동적 속성을 가질 수 있습니다.
- 인터페이스: 객체 타입을 정의하고, 확장할 수 있습니다.
- 타입 별칭: 타입을 정의하고 확장할 수 있습니다.
1. 객체 타입 선언 방법
객체의 타입을 정의할 때는 각 속성의 이름과 타입을 지정합니다.
let person: { name: string; age: number; isStudent: boolean } = {
name: "Alice",
age: 30,
isStudent: true
};
person 객체는 name, age, isStudent라는 속성을 가지며, 각각 string, number, boolean 타입을 가지고 있습니다.
2. 선택적 속성(Optional Properties)
객체의 속성 중 일부는 **선택적(optional)**으로 지정할 수 있습니다. 선택적 속성은 있어도 되고 없어도 되는 속성을 의미하며, 타입 선언에서 속성 이름 뒤에 ?를 붙여서 표시합니다.
let person: { name: string; age?: number } = {
name: "Alice"
};
age 속성은 선택적이므로 person 객체에 age가 없어도 오류가 발생하지 않습니다.
3. 읽기 전용 속성(Readonly Properties)
객체의 속성에 읽기 전용(readonly) 제약을 추가하여, 초기화 이후에는 속성의 값을 변경할 수 없도록 할 수 있습니다. readonly 키워드를 속성 앞에 붙여서 사용합니다.
let person: { readonly name: string; age: number } = {
name: "Alice",
age: 30
};
person.age = 31; // 가능
person.name = "Bob"; // 오류 발생, name은 읽기 전용 속성
4. 인덱스 시그니처 (Index Signature)
객체가 동적 속성을 가질 수 있도록, 특정 타입의 속성을 임의의 이름으로 지정할 때는 인덱스 시그니처를 사용합니다. 주로 속성 이름을 모르는 경우나, 동일한 타입의 여러 속성을 가질 수 있는 객체에 유용합니다.
let dictionary: { [key: string]: string } = {};
dictionary["hello"] = "안녕하세요";
dictionary["goodbye"] = "안녕히 가세요";
dictionary 객체가 문자열을 키로 하고, 문자열을 값으로 가지는 여러 속성을 가질 수 있음을 나타냅니다.
5. 객체 타입을 위한 인터페이스 (Interface)
객체 타입이 복잡하거나 여러 곳에서 재사용할 때는 **인터페이스(interface)**를 사용하여 타입을 정의할 수 있습니다. 인터페이스는 객체의 구조를 명확하게 정의해주며, 확장이 가능합니다.
interface Person {
name: string;
age: number;
isStudent?: boolean; // 선택적 속성
}
let alice: Person = {
name: "Alice",
age: 30
};
6. 객체 타입을 위한 타입 별칭 (Type Alias)
인터페이스와 비슷하게 타입 별칭(type alias)도 객체 타입을 정의하는 데 사용됩니다. 인터페이스와의 차이점은 주로 유니온 타입이나 복합 타입을 정의할 때 유용하다는 점입니다.
type Person = {
name: string;
age: number;
isStudent?: boolean;
};
let bob: Person = {
name: "Bob",
age: 25
};
7. 객체 타입을 확장 (Interface & Type Alias Extension)
객체 타입을 확장해서 다른 타입의 기반으로 사용할 수 있습니다.
인터페이스 확장
인터페이스는 상속이 가능하여 다른 인터페이스를 확장할 수 있습니다.
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
jobTitle: string;
}
let employee: Employee = {
name: "Charlie",
age: 40,
jobTitle: "Developer"
};
타입 별칭 확장
타입 별칭은 & 연산자를 사용하여 여러 타입을 합칠 수 있습니다.
type Person = {
name: string;
age: number;
};
type Employee = Person & {
jobTitle: string;
};
let employee: Employee = {
name: "Daisy",
age: 35,
jobTitle: "Designer"
};
# 열거형
- 숫자형 열거형: 자동으로 1씩 증가된 숫자 값을 할당받으며, 값과 이름 간 양방향 매핑이 가능합니다.
- 문자열 열거형: 각 멤버에 명시적으로 문자열 값을 할당해야 하며, 양방향 매핑은 불가능합니다.
- 이종 열거형: 숫자와 문자열을 혼합하여 사용할 수 있지만, 특별한 경우가 아니면 권장되지 않습니다.
- const 열거형: 컴파일 타임에 상수 값으로 대체되며, 성능 최적화를 위해 사용할 수 있습니다.
1. 숫자형 열거형 (Numeric Enum)
숫자형 열거형은 기본적으로 숫자 값을 자동으로 할당하는 열거형입니다. 첫 번째 값에만 숫자를 지정하면, 나머지는 1씩 증가된 값을 자동으로 할당받습니다.
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
let move: Direction = Direction.Up;
console.log(move); // 0
Direction.Up의 값은 0이고, Down은 1, Left는 2, Right는 3으로 자동 할당
enum Status {
Success = 1,
InProgress, // 2
Failed // 3
}
console.log(Status.Success); // 1
console.log(Status.InProgress); // 2
console.log(Status.Failed); // 3
숫자형 열거형의 양방향 매핑
숫자형 열거형은 값과 이름 모두로 접근할 수 있어 양방향 매핑이 가능
enum Status {
Success = 1,
InProgress,
Failed
}
console.log(Status.Success); // 1
console.log(Status[1]); // Success
2. 문자열 열거형 (String Enum)
문자열 열거형은 각 열거형 멤버에 문자열 값을 명시적으로 지정할 수 있는 열거형입니다. 문자열 열거형은 숫자형 열거형과 달리 자동 증분되지 않으며, 항상 지정된 문자열 값만 가집니다.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
let move: Direction = Direction.Up;
console.log(move); // "UP"
문자열 열거형은 특정 문자열 값만 가질 수 있으므로, 값과 이름 간의 양방향 매핑이 불가능합니다. 즉, Direction["UP"]처럼 값을 통해 열거형 이름을 가져올 수 없습니다.
3. 이종 열거형 (Heterogeneous Enum)
숫자형과 문자열형을 혼합하여 사용할 수도 있습니다. 이를 이종 열거형(Heterogeneous Enum)이라고 합니다. 그러나 실제로 이종 열거형은 특수한 경우가 아니면 잘 사용되지 않습니다. 타입 안전성을 저해할 수 있기 때문입니다.
enum Result {
Success = 1,
Failure = "FAILURE"
}
console.log(Result.Success); // 1
console.log(Result.Failure); // "FAILURE"
4. 열거형의 활용 예시
열거형은 코드의 가독성을 높이고, 고정된 값 집합을 관리하는 데 유용합니다. 주로 상태, 방향, 색상 등 유한한 값들을 표현할 때 많이 사용됩니다.
enum HttpStatus {
OK = 200,
BadRequest = 400,
Unauthorized = 401,
NotFound = 404,
InternalServerError = 500
}
function handleRequest(status: HttpStatus) {
switch (status) {
case HttpStatus.OK:
console.log("Request was successful.");
break;
case HttpStatus.NotFound:
console.log("Resource not found.");
break;
case HttpStatus.InternalServerError:
console.log("Server encountered an error.");
break;
default:
console.log("Unhandled status code:", status);
}
}
handleRequest(HttpStatus.OK); // "Request was successful."
handleRequest(HttpStatus.NotFound); // "Resource not found."
handleRequest(HttpStatus.InternalServerError); // "Server encountered an error."
5. const 열거형 (Const Enum)
const 열거형은 컴파일 타임에 인라인 처리되는 열거형입니다. 즉, 자바스크립트 코드로 컴파일될 때 실제 열거형 객체를 생성하지 않고 상수 값으로 대체됩니다. 성능 최적화가 필요할 때 사용됩니다.
const enum Direction {
Up,
Down,
Left,
Right
}
let move = Direction.Up;
console.log(move); // 0 (컴파일된 JavaScript에서는 단순히 상수 값으로 대체)
const enum은 TypeScript에서만 인식 가능하며, 열거형 값이 자바스크립트 코드에서 직접 상수 값으로 변환되어 성능을 최적화할 수 있습니다.
'TypeScript' 카테고리의 다른 글
[ TypeScript ] 개념 , 컴파일 옵션 설정 (0) | 2024.11.14 |
---|