본문 바로가기

Study/실무

Typescript Type vs interface

확장하는 방법

interface UserInterface {
  id: number
  name: string
}

interface InfoInterface extends UserInterface {
  age: number
}
type UserType {
  id: number
  name: string
}

type InfoType = UserType & {
  age: number
}

 

 

선언적 확장 (선언병합)

type은 새로운 속성을 추가하기 위해서 다시 같은 이름으로 선언할 수 없지만, 

interface는 항상 선언적 확장이 가능합니다. 

interface Window {
  title: string;
}

interface Window {
  ts: import("typescript");
}

// 같은 interface 명으로 Window를 다시 만든다면, 자동으로 확장이 된다.
declare function getWindow(): Window;

const window = getWindow();
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});    // transpileModule() 메서드 사용 가능
type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

// Error: Duplicate identifier 'Window'.
// 타입은 안된다.

 

interface는 객체에만 사용이 가능합니다.

interface FooInterface {
  value: string
}

type FooType = {
  value: string
}

type FooOnlyString = string
type FooTypeNumber = number

// 불가능
interface X extends string {}

  

성능을 위해서는 interface를 사용하는 것이 좋습니다.

여러 type 혹은 interface를 &하거나 extends할 때를 생각해보자. 
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)

 

따라서 타입 간 속성을 머지 할 때는 주의를 필요로 한다. 어차피 객체에서만 쓰는 용도라면, interface를 쓰는 것이 훨씬 좋습니다.

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'

interface 들을 합성할 경우 이는 캐시가 되지만, 타입의 경우에는 그렇지 못합니다.

Type 합성의 경우, 합성에 자체에 대한 유효성을 판단하기 전에,

모든 구성요소에 대한 타입을 체크하므로 컴파일 시에 상대적으로 성능이 좋지 않다.

 

 

TypeScript 팀의 의도

TypeScript 팀은 개방-폐쇄 원칙에 따라 확장에 열려있는 JavaScript 객체의 동작 방식과
비슷하게 연결하도록 Interface를 설계했습니다.

그래서 TypeScript 팀은 가능한 Type Alias보단 Interface를 사용하고,
합 타입 혹은 튜플 타입을 반드시 써야 되는 상황이면 Type Alias를 사용하도록 권장하고 있습니다.

 

 

 

 

 

참조

https://medium.com/humanscape-tech/type-vs-interface-%EC%96%B8%EC%A0%9C-%EC%96%B4%EB%96%BB%EA%B2%8C-f36499b0de50

https://yceffort.kr/2021/03/typescript-interface-vs-type

'Study > 실무' 카테고리의 다른 글

useQuery  (0) 2022.10.05
useMutation  (0) 2022.10.05
window.location.href vs useNavigate vs Link  (0) 2022.10.04
web3-react를 이용한 메타마스크,코인베이스 지갑 연동  (0) 2022.10.04
useRef 를 사용하여 scrollEvent 만들기  (0) 2022.10.04