인프런 캡틴판교님의 타입스크립트 강의를 들으며 정리한 interface와 타입별칭에 관한 글입니다.
Today’s Key Point
1. Interface
2. Type Aliases
3. Interface 와 Type Aliases 차이
Type정의 즉 Type Annotation을 하다보면 반복적인 타입들을 계속 정의해줘야하는 경우가 생깁니다.
예를 들어 todo list의 item들은 항상 같은 타입 형태입니다.
let todoItems = [
{ id: 1, title: '안녕', done: false },
{ id: 2, title: '타입', done: false },...
]
이런식으로 말이죠!
이 todoItems에 타입을 정의하자면 아래와 같을 것입니다.
// 방법1
let todoItems: object[]
// 방법 2
let todoItems: { id: number; title: string; done: boolean}[]
여기까지는 문제가 없지만, todo를 구현할 때에 각각의 item을 추가, 수정, 삭제 등을 하는 함수를 구현할 경우마다 인자 혹은 반환값으로 사용될 타입 정의에 모두 위와 같은 타입을 반복적으로 작성해줘야한다는 것입니다.
function fetchTodos(): { id: number; title: string; done: boolean}[] {
const todos = fetchTodoItems();
return todos;
}
function addTodo(
todo: { id: number; title: string; done: boolean}[]
): void {
todoItems.push(todo);
}
function completeTodo(
index: number,
todo: { id: number; title: string; done: boolean}[]
): void {
todo.done = true;
todoItems.splice(index, 1, todo);
}
이런식으로 작성하게 된다면, 코드의 가독성과 효율성 면에서 상당히 불리하다고 느껴집니다.
이럴때, Interface
사용하여 위와 같은 문제를 해결할 수 있습니다.
상호간에 정의한 약속 혹은 규칙으로 반복되는 타입을 정의하여 사용할 수 있습니다.
인터페이스를 주로 사용하는 경우는 아래와 같습니다.
사용법
interface User {
name: string;
age: number;
}
사용예제
변수에 사용하는 경우
const seho: User = { name: 'hi', age: 100 };
함수의 매개변수에 사용하는 경우
function getUser(user: User) {
console.log(user);
}
getUser(seho);
함수의 스펙(구조)에 사용하는 경우
// 함수의 인수, 반환값까지 모두 한번에 정의가능
interface SumFunction {
(a: number, b: number): number;
}
let sum: SumFunction;
sum = function (num1: number, num2: string): number {
return num1 + num2;
};
배열의 인덱싱에 사용하는 경우
interface StringArray {
[index: number]: string;
}
let arr: StringArray;
arr[0] = 'hi';
arr[1] = 10; // error
딕셔너리 패턴 (key-value 형태를 지닌 자료형 js에서는 객체)
interface StringRegexDictionary {
[key: string]: RegExp;
}
let obj: StringRegexDictionary = {
cssFile: /\.css$/,
jsFile: /\.js$/
}
// => 객체의 key(index)를 접근할 때 유용
Object.keys(obj).forEach((value)){
})
인터페이스 확장
// 기본 interface
interface Person {
name: string;
age: number; // 옵셔널 선택자 ? 동일하게 적용 가능
}
// 위와 같은 타입을 갖고있으며, language 속성을 추가하여 확장한 interface
interface Developer extends Person {
language: string;
}
// 확장된 Developer interface를 활용한 타입 정의
const joo: Developer = { name: 'joo', age: 20, language: 'ts' };
사용법
type MyName = string;
const name: MyName = 'capt';
언뜻보면 interface
와 너무나도 유사해보입니다.
하지만, 타입별칭은 그저 편하게 사용하기 위한 별칭일뿐 새로운 타입을 하나 생성한 것이라도 보기 어렵습니다.
⭐ 여기서 Interface
와 Type Aliases
의 차이점을 짚고 넘어가보겠습니다!
1. 타입의 목적성 유무
위의 설명의 연장선으로 Type Aliases
는 새로운 타입값을 하나 생성하는 것이 아니라 단순히 정의한 타입을 나중에 쉽게 참고할 수 있게 이름을 부여하는 것과 같습니다.
2. 확장성의 유무
interface
는 확장이 가능한데 반해 타입별칭은 확장이 불가능합니다.
따라서 가능한 type
보다는 interface
로 선언해서 사용하는 것을 추천합니다.