[TS] 타입스크립트 타입과 타입 선언 방법을 알아보자
타입스크립트 타입과 타입 선언 방법을 알아보자
TypeScript를 사용해서 코드의 오류를 사전에 방지하고 유지보수성을 향상시킬 수 있다. 이번 글에서는 TypeScript의 기본 타입과 선언 방식을 알아보자!
TypeScript의 타입 시스템
TypeScript
의 가장 큰 특징 중 하나는 정적 타입 시스템
을 제공하는 점이다. 이는 변수나 함수의 타입을 명시적으로 선언하며, 컴파일 시점에 오류를 잡을 수 있도록 해줌
1-1) 기본 타입 (Primitive Types)
TypeScript는 JavaScript에서 사용되는 기본적인 타입들을 그대로 사용할 수 있다.
-
string
: 문자열 타입
let name: string = "rarrit";
-
number
: 숫자 타입
let age: number = 25;
-
boolean
: 불리언 타입(참/거짓)
let isBoy: boolean = true;
-
null
과undefined
: 각각 비어있음을 나타내는 타입
let n: null = null;
let u: undefined = undefined;
-
any
: 모든 타입을 허용하는 타입
let value: any = 1;
value = "rarrit"; // 가능함
-
void
: 반환 값이 없음을 의미하는 타입, 주로 함수에서 사용함
function sayHi(): void {
console.log("hi");
}
1-2) 배열과 튜플 (Array & Tuples)
배열과 튜플은 여러 값을 담을 수 있는 자료 구조로, TypeScript에서는 배열의 타입을 명시적으로 선언할 수 있다.
-
배열
: 배열의 요소 타입을 명시할 수 있음
let numbers: number[] = [1,2,3];
let strings: string[] = ["a", "b", "c"];
-
튜플
: 고정된 길이와 타입을 가지는 배열
let tuple: [string, number];
tuple = ["rarrit", 30];
타입 선언 방식
TypeScript
에서 타입을 선언하는 방법은 간단하다. 변수를 선언할 때 타입을 명시하거나, 함수를 작성할 때 매개변수와 반환 타입을 지정할 수 있다.
2-1) 변수 선언 시 타입 지정
변수를 선언할 때 타입을 명시적으로 지정하면, 그 변수는 해당 타입의 값만 할당받을 수 있음
let username: string = "rarrit";
let age: number = 30;
let isBoy: boolean = true;
2-2) 함수 선언 시 타입 지정
함수의 매개변수와 반환값에 타입을 지정할 수 있으며, 이를 통해 함수를 사용할 때 발생할 수 있는 오류를 사전에 방지함
function add(a: number, b:number): number {
return a + b;
}
let noneFunc: () => void;
noneFunc = function () {
console.log('hihi');
};
2-3) 인터페이스 (interface)
interface
는 객체의 구조를 정의할 때 사용한다. 객체의 속성 타입을 명확하게 정의하여 안전한 코드를 작성할 수 있게 해줌
interface Todo {
title: name;
completed: boolean;
}
const todo: Todo = {
title: "todo",
completed: false;
}
2-4) 타입 별칭 (Type Aliases)
타입 별칭을 사용하면 특정 타입에 이름을 붙여 사용할 수 있다. 복잡한 타입을 쉽게 재사용 가능함
type ID = number | string;
let userId: ID = 111;
userID = "zzz111" // 가능함
type ExampleType = {};
type StringType = string;
type UnionType = string | number
2-5) Type alias vs interface
TS Documents 내용을 간략히 설명하면 “둘 다 매우 유사하고 많은 경우 자유롭게 선택할 수 있다!” 이다. 하지만 확장성
과 복잡한 타입 표현
에서 차이가 있는데, 아래의 차이점을 보고 상황에 맞게 사용하면 됨
-
확장성(Extensibility)
-
interface
- 인터페이스는 항상 확장이 가능하며, 다른 인터페이스를 상속하거나 동일한 이름으로 다시 열어 새로운 속성을 추가할 수 있음
-
type alias
- 타입 별칭은 한 번 정의되면 다시 열어 새로운 속성을 추가할 수 없으며, 동일한 타입에 새로운 속성을 추가해야 하는 경우 인터페이스가 유리함
-
interface
interface Hello {
name: string
}
interface Hello {
age: number
} // ✅ 가능, Hello 는 name 과 age 모두를 포함하게 됨
type Hello2 = {
name: string
}
type Hello2 = {
age: number
} // 🙅♂️ 불가능
-
복잡한 타입 표현
-
interface
- 객체 형태의 타입을 정의하는 데에 주로 사용된다.
-
type alias
- 객체 형태 뿐만 아니라, 유니온 타입, 튜플, 매핑된 타입 등 복잡한 타입 표현에 유리함
-
interface
2-6) 구조적 타입 시스템
TypeScript
의 타입 시스템은 구조적 타입 시스템이다. 구조적 타입 시스템에서는 값의 형태와 구조에 따라 타입이 결정된다. 즉, 타입이 실제로 어떻게 선언되었는지가 아니라 어떤 프로퍼티와 메서드를 가지고 있는지가 중요함.
- “만약 어떤 새가 오리처럼 걷고, 오리처럼 소리 내고, 오리처럼 행동한다면, 나는 그 새를 오리라고 부를 것이다.”
- 같은 개념은 아니지만 Duck Typing의 유래는 구조적 타이핑을 이해하는 데에 도움이 된다.
- 두 개념 다 간단히 말해서, 똑같이 생겼다면 이름이 뭔지는 모르겠지만, 같은 타입으로 간주한다.
유니언과 교차 타입 (Union & Intersection Type)
TypeScript
는 여러 타입을 결합하거나, 여러 타입을 동시에 만족하는 타입을 정의할 수 있는 유니언과 교차 타입을 제공함
3-1) 유니언 타입 (Union Type)
하나 이상의 타입을 허용하는 경우 유니언 타입을 사용할 수 있음.
let id: number | string;
id = 010; // number 타입 가능
id = "zeronezero" // string 타입 가능
3-2) 교차 타입 (Intersection Type)
여러 타입을 결합하여 하나의 새로운 타입을 정의할 수 있음. 교차 타입은 두 가지 이상의 타입을 모두 만족해야 함
interface Skills {
skill: string;
}
interface Infos {
desc: string;
}
type Champion = Skills & Infos;
const ezreal: Champion = {
skill: "비전 이동",
desc: "노랑 머리 원딜"
}
마무리
TypeScript
는 정적 타입 시스템을 통해 코드의 오류를 사전에 방지하고, 유지보수성을 높이는 데 큰 도움을 준다. 기본 타입부터 배열과 튜플, 인터페이스와 타입 별칭, 그리고 유니언과 교차 타입까지, 다양한 타입 시스템을 이해함으로써 더욱 안전하고 안정적인 코드를 작성할 수 있을 것 같다.