Interface 와 Type 의 차이 [TIL / TypeScript]

알락·2023년 2월 27일
0

타입스크립트를 공부하다보면 아마 대부분이 Interface와 Type의 역할이 거의 똑같은 데 왜 구분해서 사용하는지 의문이 들게 된다. 두 구문에 대한 예시는 다음과 같다.

[Interface, Type 사용 예시]

// Interface
interface withInterface {
    propertyString: string
    propertyNumber: number
}

const instanceInterface: withInterface = {
    propertyString: 'Hello',
    propertyNumber: 1
}

// Type
type withType = {
    propertyString: string
    propertyNumber: number
}

const instanceType: withType = {
    propertyString: 'Hi',
    propertyNumber: 2
}

console.log(`Interface: ${instanceInterface}`); // Ok
console.log(`Type: ${instanceType}`); // Ok

선언과 할당이 거의 비슷하게 작성되어지고 있어서 뚜렷한 차이가 없어 보인다. ⌜러닝 타입스크립트⌟에서는 객체 할당 같은 경우 많은 프로젝트에서 Interface를 사용한다고 간단하게 설명되어 있다. 어찌됐든, Interface와 Type을 따로 마려해 둔 이유는 있을 것이다. 그 실마리를 잡고자 글을 작성하며 정리해본다.

Type

Type 별칭은 type 타입이름 = type형의 형식으로 작성이 되어진다. 그리고 타입 어노태이션을 이용해서 변수에 할당 가능한 타입을 지정하는데 사용된다.

[Type의 타입 어노태이션]

type fruit = string;

const fruitName: fruit = 'banana'; // Ok

Type 별칭은 추가적인 기능은 없다. 변수에 할당될 수 있는 타입 지정이 길어지는 경우가 있는데, 이럴 경우 Type 별칭으로 따로 작성해두고 필요한 부분에 이름만 지정하면 쉽게 재사용이 가능해진다.

Interface

Interface는 Java의 Interface를 선언하고 사용하는 것처럼 작성되어진다. interface 인터페이스명칭 {...}의 형식이다. 그래서 사실 Interface는 type처럼 객체를 제외하고 사용할 수는 없는 것 같다. 한 번 실험해봤다.

[Interface 객체 없이 사용]

type withoutObjectType = string; // Ok

interface withoutObject = string;
// 'string' only refers to a type, but is being used as a value here.
interface withoutObject: string;
// 'string' only refers to a type, but is being used as a value here.

interface withObject {}
const instanceWithObj: withObject = {}; // Ok

Type vs Interface

타입을 할당해서 사용한다. / 틀을 마련해서 사용한다.

결국 객체의 형태로 Type과 Interface를 사용하게 되면 기능상으로는 구분하기가 어려워지는 것 같다. 둘 다 타입 어노테이션을 통해서 타입을 지정해서 사용할 수 있다는 공통점도 가지고 있다.

그래도 구분해보고자 하는 노력으로 볼 수 있는 둘의 차이점은 하나는 할당의 형태로 작성이 되고 하나는 선언의 형태로 작성이 된다는 것이다.

Interface 확장

Interface는 Type과 비교했을 때 추가적으로 제공해주는 기능이 있다. 확장(extends) 기능이다. extends만 놓고 보면 자바의 상속 기능과 비슷하게 느껴질 수도 있다.

[extends 예시]

interface withInterface {
    propertyString: string
    propertyNumber: number
}

interface withExtends extends withInterface {
    propertyNumberAdded: number
}

const instanceInterface: withInterface = {
    propertyString: 'Hello',
    propertyNumber: 1
}

const wrongExtends: withExtends = {
    propertyString: '안녕하세요',
    propertyNumber: 2
} 
// Property 'propertyNumberAdded' is missing in 
// type '{ propertyString: string; propertyNumber: number; }' 
// but required in type 'withExtends'.

const correctExtends: withExtends = {
    propertyString: '안녕하세요',
    propertyNumber: 3,
    propertyNumberAdded: 4
} // Ok

Interface 병합

Interface는 같은 스코프 안에서 동일한 이름을 갖는 Interface가 있다면 둘을 병합하여 사용할 수 있다. 다음의 예시로 확인할 수 있다.

/* Interface Merge */
interface withInterface {
    propertyString: string
    propertyNumber: number
}

interface withInterface {
    propertyNumberAdded: number;
}

const correctExtends: withExtends = {
    propertyString: '안녕하세요',
    propertyNumber: 3,
    propertyNumberAdded: 4
}

/*  Type */
type withType = {
    propertyString: string
    propertyNumber: number
}

type withType = {
    propertyNumberAdded: number
}
// Duplicate identifier 'withType'.

withInterface는 작성되어야 하는 프로퍼티를 추가함으로써 병합이 된다. 하지만 withType은 똑같은 식별자가 사용되고 있다는 경고문구를 출력하고 있다.

⌜러닝 타입스크립트⌟에서도 사실 개발에서 Interface 병합으로 이해하기 어려운 코드를 우려하여 권하지 않는 방법이라고 한다. 하지만 외부 패키지나 전역 인터페이스를 사용할 때 강점이 있다고 얘기한다.

이외의 차이점

  • Class의 구조 타입 확인에는 Interface 밖에 사용을 못한다.
  • Interface의 타입 검사기가 더 빨리 작동한다.
  • Interface가 명명된 객체로 간주되어 오류 메시지의 가독성이 좋다.

결론

프로젝트가 복잡해지고 다양한 타입스크립트의 기능을 사용하길 원한다면 Interface를 이용하는 것이 좋을 것 같다. 하지만 간단한 타입 지정은 Type과 Interface의 차이는 크게 없어 보인다.

profile
블록체인 개발 공부 중입니다, 프로그래밍 공부합시다!

0개의 댓글