기술 측면
// 타입 type PositionType = { x: number; y: number; } // 인터페이스 interface PositionInterface { x: number; y: number; }
공통점
- 객체의 타입을 정의하는 데 사용할 수 있다.
- 클래스를 구현(implements)하는 데 사용할 수 있다.
class Pos1 implements PositionType { x: 1; y: 2; } class Pos2 implements PositionInterface { x: 1; y: 2; }
- 확장(Extends)할 수 있다.
// type은 인터섹션 연산자로 확장 type ZPositionType = PositionType & { z: number }; // interface는 상속을 통해 확장 (또는 선언적 병합) interface ZPositionInterface extends PositionInterface { z: number; };
type은 원래 확장이 불가능했으나, 최근 버전에서 가능해졌다.
차이점
- interface만 병합(merge)할 수 있다. (선언적 확장)
interface Box { height: number; width: number; } interface Box { scale: number; } let box: Box = {height: 5, width: 6, scale: 10};
- Type만 computed properties를 사용할 수 있다. (계산된 프로퍼티)
type Person = { name: string, age: number } type Name = Person['name']; // string
- interface는 객체에만 사용이 가능하다. type은 객체 외에도 원시값, 유니온 타입, 튜플 등에도 사용할 수 있다.
interface FooInterface { value: string } type FooType = { value: string } type FooOnlyString = string type FooTypeNumber = number
개념 측면
Interface
정의: “어떤 것의 스펙, 규격 사항”
클래스, 라이브러리 등에 대한 규격을 정의하는 경우 적합하다.
어떤 것을 구현하기 위해 참고하는 문서로 생각할 수 있다.
“이 클래스는 이 인터페이스를 구현한다 (O)”
“이 클래스는 이 타입을 구현한다 (❓)”
Type
정의: “어떤 데이터의 타입(형태)”
데이터의 형태를 묘사한다. 데이터를 담을 목적인 경우 적합하다.
“이 컴포넌트에 전달할 수 있는 Props 타입은 이 Type이다 (O)”
“이 컴포넌트에 전달할 수 있는 Props 타입은 이 interface이다(❓)”
결론
- 대부분의 경우 타입과 인터페이스는 유사하다.
코드베이스에서 일관성을 유지하는 것이 더 중요하다.
- 복잡한 타입을 다룰 때에는 type을 사용하는 것이 좋다. (계산된 프로퍼티)
- 컴포넌트의 props와 state에 대한 타입을 선언할 때 Type을 사용하는 것이 적합하다. 의미적으로 적합하며, 더 제한적이기 때문에 유리하다.
interface를 사용해도 괜찮다. 일관성을 유지하는 것이 더 중요하다.
- 클래스, 라이브러리를 제작할 때는 인터페이스를 사용하라. 의미적으로 적합하며, 상속을 통해 확장이 필요할 때 더 유리하다.
- 서버에서 받아오는 API 응답은 type으로 정의하는 것이 의미상 적절하다.
클라이언트와 서버가 주고 받는 데이터의 형태를 정의하는 것이기 때문이다.
이
이펙티브 타입스크립트
- 대부분의 경우에는 타입을 사용해도 되고 인터페이스를 사용해도 됩니다. 그러나 타입과 인터페이스 사이에 존재하는 차이를 분명하게 알고, 같은 상황에서는 동일한 방법으로 명명된 타입을 정의해 일관성을 유지해야 합니다.
- 복잡한 타입이라면 고민할 것도 없이 타입을 사용하면 됩니다. 그러나 타입과 인터페이스, 두 가지 방법으로 모두 표현할 수 있는 간단한 객체 타입이라면 일관성과 보강의 관점에서 고려해 봐야 합니다. 일관되게 인터페이스를 사용하는 코드베이스에서 작업하고 있다면 인터페이스를 사용하고, 일관되게 타입을 사용 중이라면 타입을 사용하면 됩니다.
- 아직 스타일이 확립되지 않은 프로젝트라면, 향후에 보강의 가능성이 있을지 생각해 봐야 합니다. 어떤 API에 대한 타입 선언을 작성해야 한다면 인터페이스를 사용하는 게 좋습니다. API가 변경될 때 사용자가 인터페이스를 통해 새로운 필드를 병합할 수 있어 유용하기 때문입니다. 그러나 프로젝트 내부적으로 사용되는 타입에 선언 병합이 발생하는 것은 잘못된 설계입니다. 따라서 이럴 때는 타입을 사용해야 합니다.