interface PeopleInterface {
name: string
age: number
}
const me1: PeopleInterface = {
name: 'yc',
age: 34,
}
type PeopleType = {
name: string
age: number
}
const me2: PeopleType = {
name: 'yc',
age: 31,
}
위에서 볼 수 있는 것 처럼, interface는 타입과 마찬가지로 객체의 타입의 이름을 지정하는 또 다른 방법이다.
차이점 - 확장하는 방법
interface PeopleInterface {
name: string
age: number
}
interface StudentInterface extends PeopleInterface {
school: string
}
type PeopleType = {
name: string
age: number
}
type StudentType = PeopleType & {
school: string
}
차이점 - 선언적 확장
interface에서 할 수 있는 대부분의 기능들은 type에서 가능하지만, 한 가지 중요한 차이점은 type은 새로운 속성을 추가하기 위해서 다시 같은 이름으로 선언할 수 없지만, interface는 항상 선언적 확장이 가능하다는 것이다.
interface Window {
title: string
}
interface Window {
name: string
}
// 같은 interface 명으로 Window를 다시 만든다면, 자동으로 확장이 된다.
type Window = {
title: string
}
type Window = {
name: string
}
// Error: Duplicate identifier 'Window'.
// 타입은 안된다.
computed value의 사용
type은 가능하지만 interface는 불가능
type names = 'firstName' | 'lastName'
type NameTypes = {
[key in names]: string
}
const yc: NameTypes = { firstName: 'hi', lastName: 'yc' }
interface NameInterface {
// error
[key in names]: string
}
type | interface ?
여러 type 혹은 interface를 &하거나 extends할 때를 생각해보자.
interface는 속성간 충돌을 해결하기 위해 단순한 객체 타입을 만든다.
왜냐하면 interface는 객체의 타입을 만들기 위한 것이고, 어차피 객체 만 오기 때문에 단순히 합치기만 하면 되기 때문이다.
그러나 타입의 경우, 재귀적으로 순회하면서 속성을 머지하는데, 이 경우에 일부 never가 나오면서 제대로 머지가 안될 수 있다. interface와는 다르게, type은 원시 타입이 올수도 있으므로, 충돌이 나서 제대로 머지가 안되는 경우에는 never가 떨어진다. 아래 예제를 살펴보자.
type type2 = { a: 1 } & { b: 2 } // 잘 머지됨
type type3 = { a: 1; b: 2 } & { b: 3 } // resolved to `never`
const t2: type2 = { a: 1, b: 2 } // good
const t3: type3 = { a: 1, b: 3 } // Type 'number' is not assignable to type 'never'.(2322)
const t3: type3 = { a: 1, b: 2 } // Type 'number' is not assignable to type 'never'.(2322)
type t1 = {
a: number
}
type t2 = t1 & {
b: string
}
const typeSample: t2 = { a: 1, b: 2 } // error
// before(3.x): Type 'number' is not assignable to type 'string'.
// after(4.x): Type 'number' is not assignable to type 'string'.(2322) input.tsx(14, 5): The expected type comes from property 'b' which is declared here on type 't2'
4.x 부터는 에러 원인을 알려준다.
interface 들을 합성할 경우 이는 캐시가 되지만, 타입의 경우에는 그렇지 못하다.
type 합성의 경우, 합성에 자체에 대한 유효성을 판단하기 전에, 모든 구성요소에 대한 타입을 체크하므로 컴파일 시에 상대적으로 성능이 좋지 않다.
무엇이 되었건 간에, 프로젝트 전반에서 type을 쓸지 interface를 쓸지 통일은 필요해보인다. 그러나 객체, 그리고 타입간의 합성등을 고려해 보았을 때 interface를 쓰는 것이 더 나을지 않을까 싶다.
'TypeScript' 카테고리의 다른 글
[TypeScript] 제네릭(Generic) 타입은 무엇인가? (0) | 2023.01.29 |
---|---|
[TypeScript] 열거형(Enum) 타입은 무엇인가? (0) | 2023.01.29 |
[TypeScript] 리터럴 타입, 유니언 타입, 교차 타입 설명 (0) | 2023.01.29 |