최근 30분간 동시 방문자 수를 표시합니다. (~)
최고 동시 방문자 수 -
어제: 0명 / 오늘: 0명
타입스크립트를 주제로 자주 받는 질문 중 하나가 객체 타입을 정의할 때 interface와 type 키워드 중 무엇을 사용하는 것이 좋겠냐는 것입니다.
일단 타입스크립트 공식 문서에서는 다음과 같이 설명합니다.
Differences Between Type Aliases and Interfaces -
For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use interface until you need to use features from type.
정리하자면, interface와 type 키워드는 개인적인 선호나 상황에 따라 선택하되, 굳이 기준을 제시하자면 type이 필요한 상황이 되기 전에는 interface를 사용하라는 것입니다.
위 내용과 별개로도 저는 객체 타입을 정의할 때 주로 interface를 사용하는데, 가장 큰 이유는 선언 병합이 가능하기 때문입니다.
선언 병합(Declaration Merging)은 같은 이름의 interface를 여러 번 선언하면 하나로 병합되어 확장되는 것을 말합니다.
1234567891011interface User { name: string } interface User { age: number } const user: User = { name: 'Neo', age: 85 }
그래서 기존에 인터페이스로 선언된 객체 타입에 새로운 속성을 추가할 때 유용합니다.
예를 들면, 다음과 같이 전역 객체에 원하는 속성을 추가할 수 있습니다.
12345declare global { interface Window { hello?: string } }
1window.hello = 'Hello world!'
그리고 사용하는 라이브러리를 직접 수정하지 않고도 인터페이스로 정의된 특정 객체 타입을 확장할 수 있습니다.
1234567import 'axios' declare module 'axios' { interface AxiosRequestConfig { hello?: string } }
12345import axios from 'axios' axios({ hello: 'Hello world!', })
예를 들어 Vue는 컴포넌트에서 사용하는 전역 속성을 추가할 때, 컴포넌트 타입을 직접 수정하는 대신 별도로 제공되는 ComponentCustomProperties 타입을 통해 확장합니다.
복잡한 기존 타입의 직접 수정은 예기치 않은 문제를 일으킬 수 있기 때문에 기존 타입을 유지하면서 새로운 속성을 추가하는 방법을 제공하는 것입니다.
직접 라이브러리를 만들 때도 보다 안전한 타입을 제공하는 유용한 방법입니다.
12345678import axios from 'axios' declare module 'vue' { interface ComponentCustomProperties { $http: typeof axios $translate: (key: string) => string } }
1234<template> <button @click="$http.get('/api/user')">Fetch User</button> <p>{{ $translate('hello') }}</p> </template>
이런 이유 등으로 저는 객체 타입을 정의할 때 interface 키워드 사용을 추천합니다.
물론 명확한 이유나 상황이 없다면 개인적인 선호는 충분히 다를 수 있습니다.