안녕하세요~~ 오늘은 Typescript에서 쓰이는 interface와 type의 차이에 대해 알아보려고 합니다.😎
interface와 type은 둘다 타입을 지정해줄 때 쓰는데 정확히 어떤 차이가 있을까요?
크게 5가지의 차이점을 알아보겠습니다.
그럼 하나씩 알아볼까요~? 🤓🤓
interface, type은 각각 지정할 수 있는 타입의 차이가 있습니다. 한번 알아봅시다. 😎
interface는 ❗️오직❗️ 객체를 지정할 때만 쓰입니다.
interface Person {
name: string
age: number
}
const person: Person = {
name: 'jiveloper',
age: 27
};
type은 interface 처럼 객체 타입에도 선언하지만 주로 원시값, 튜플 등의 타입을 선언할 때 쓰입니다.
🤔: 객체 타입을 지정하는 부분은 interface와 역할이 동일하나, 내가 알아봤을 때는 일반적으로는 객체의 타입을 지정할 때 interface를 사용하는게 코드컨벤션 식으로 자리 잡은듯 하다...
type Person = {
name: string
age: number
}
const person: Person = {
name: 'jiveloper',
age: 27,
};
🤩: 이 부분은 이번에 처음 알게 된 사실인데, 페이로드에 대해서도 타입으로 지정할 수 있다는 것이다!!!!! 커스텀 타입으로 자주 애용해야겠습니다~!
const person = {
id: 1,
name: "jiveloper",
job: {
developer: true
},
age: 27
}
type Person = typeof person;
type Name = string
type Age = number
type NumberString = string | number // union 타입
type Person = [string, number, boolean]
interface와 type은 모두 타입 확장이 가능하나, 확장 방법에 차이가 있습니다.
interface는 extends 예약어를 통해 타입을 확장할 수 있습니다.
interface Person {
name: string
age: number
}
interface Student extends Person {
school: string
}
type은 & 연산자를 통해 타입을 확장할 수 있습니다.
type Person = {
name: string
age: number
}
type Student = Person & {
school: string
}
interface는 선언적으로 확장할 수 있고, type은 선언적으로 확장할 수 없습니다.
선언적으로 확장한다는 말이 무슨 말일까요?
똑같은 이름으로 interface를 선언하면 타입을 확장한다는 뜻입니다. 예시를 통해 알아보겠습니다.
interface Person {
name: string
}
interface Person {
age: number
}
두 interface의 이름이 Person으로 동일하죠?
변수명이나 함수명 같은 경우는 동일한 이름으로 선언되면 duplicate error가 나는데 interface는 에러가 나지 않고 타입을 확장하는 역할을 합니다.
😲: 위와 같이 쓴다면 A 개발자가 Person이라는 이름으로 interface를 선언하였는데, B 개발자가 그것을 못 보고 또 Person이라는 이름으로 interface를 선언할 수 있습니다. 그러면 의도와는 다르게 중복으로 interface가 선언된 경우에 캐치하기 힘들 수 있으니 조심할 필요가 있습니다.
선언적 확장 불가능
interface는 computed value가 사용 불가능하고, type은 computed value가 사용 가능합니다.
computed value 사용 불가능
또 어려운 말이 나왔는데, computed value가 무엇일까요?
번역하면 "계산된 값"이라는 뜻인데요, 어떻게 사용되는지 예시를 통해 알아봅시다.
type names = 'firstName' | 'lastName'
type NameTypes = {
[key in names]: string
}
const myName: NameTypes = { firstName: 'veloper', lastName: 'ji' }
NameTypes의 key타입에 names라는 union 타입이 합쳐졌습니다.
이렇게 계산된 NameTypes는 myName이라는 객체의 타입으로 지정할 수 있습니다.
TypeScript Wiki에 의하면 아래와 같이 설명되어있습니다.
Type relationships between interfaces are also cached, as opposed to intersection types as a whole.
interface 들을 합성할 경우 이는 캐시가 되지만, type의 경우에는 그렇지 못하다.
A final noteworthy difference is that when checking against a target intersection type, every constituent is checked before checking against the "effective"/"flattened" type.
type 합성의 경우, 합성에 자체에 대한 유효성을 판단하기 전에, 모든 구성요소에 대한 type을 체크하므로 컴파일 시에 상대적으로 성능이 좋지 않다.
비교적 어려운 말인데 interface는 합성 할 때 캐싱이 되기 때문에, type 보다 비교적 성능이 좋다고 이해했습니다.