
Type과 Interface 모두 사전에 타입에 대한 정의를 함으로써 변수 사용에 있어 예상치 못한 다른 타입이 유입되는 것을 방지할 수 있다.
그래서 표면적으로 본다면, 둘 다 똑같은 기능을 한다고 볼 수 있다.
실제로 코드를 보면,
type User = {
id : string;
password : string;
role : string;
}
interface User = {
id : string;
password : string;
role : string;
}
let user1: User = {
id : "park",
password : "1234",
role : "ADMIN"
}
위의 코드처럼 변수의 선언부만 다를 뿐, 똑같은 문법으로 되어있는 것을 볼 수 있다.
그렇다면 왜 굳이굳이 type과 interface가 나누어져 있는 것일까?
지금부터는 type과 interface 각각 그들만 가지고 있는 특징에 대해서 알아보려고 한다.
Type
Type의 경우, 모든 자료형에 대한 타입을 정의할 수 있다.
type Name : string;
type Age : number;
type Role = [string, number, boolean]; // 튜플
type NumStr = string | number; // union 타입
type User = {
name : string;
age : number;
}
Interface
interface의 경우, 오직 객체 타입에 대해서만 타입을 정의할 수 있다.
interface User {
name : string;
age : number;
}
위의 차이점을 볼 때, 사람마다 스타일이 다르겠지만, 뭔가 틀을 잡는 자료형(객체)의 경우에는 interface를 사용하는게 좋을 것 같고, 그 외 타입에 대해서는 Type을 사용하는게 코드의 가독성을 올려줄 수 있을 것 같다는 생각이 들었다.
Interface
interface User {
name : string;
age : number;
}
interface Employee extends User {
dept : string;
}
const engineer : Employee = {
name : "park",
age : 27,
dept : "IT Team"
}
위처럼, interface의 경우에는 extends를 통해 타입 확장이 가능하다.
Type
type User = {
name : string;
age : number;
}
type User2 = User & {
dept : string;
}
type의 경우, &연산자를 통해 확장이 가능하다.
뭔가, 직관적으로 확장에 대한 문법이 깔끔하다고 느껴지는 건 interface인 것 같다.
또한,
interface Person {
name : string;
}
interface Person {
age : number;
}
let user : Person = {
name : "park",
age : 27
}
위의 코드처럼, interface는 선언적 확장이 가능하다.
선언적 확장은 같은 interface를 추가로 선언함으로서 프로퍼티를 추가할 수 있는 방법이다.
하지만, Type의 경우 선언적 확장이 불가능하다.
이러한 특징을 보았을 때, 타입의 확장면에 있어서는 type보단 interface가 더 용이하다고 느껴진다.
우선, computed property name은
type player = 'id' | 'group';
type playerType = {
[key in player]: string;
}
const user1: playerType = {
id : "park",
group : "officer"
};
위의 코드처럼 객체타입에 사용된 key값을 미리 정의해두고 사용하는 문법이다.
이 computed property name 문법은 오로지 type일 경우만 사용할 수 있다. (interface는 사용 불가)
외관적으로는 interface나 type이나 매우 유사하다는 생각이 들었지만, 디테일하게 봤을 땐 그 차이점이 분명 존재했다.
프로젝트를 진행하면서, 그 상황에 맞게 팀원들과 코드 컨벤션을 정해서 사용하는 것이 가장 적절하다고 생각한다.