type
은 모든 유형의 타입을 정의할 수 있고 중복 정의 문제가 발생하지 않는다는 특징이 있다.
반면 interface
는 객체 상속을 지원한다.
type Point = {
x: number;
y: number;
};
// Exactly the same as the earlier example
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
위 예시 코드와 같이 interface
를 사용하지 않아도 Point라는 객체의 형태를 type
을 통해서 지정해줄 수 있다는 것!
또 아래 코드처럼 type
을 사용해 공용체(union)의 타입또한 지정해줄 수 있다.
type ID = number | string;
공용체(Union)가 무엇인가?
공식문서를 참고해보면 둘 이상의 다른 타입으로 구성된 타입으로, 해당 타입 중 하나일 수 있는 값을 나타내는걸 의미한다.
인터페이스는 객체(파이썬을 오래 사용해서 그런가 객체,오브젝트보다 딕트, 딕셔너리가 더 편하다..흑)의 구조를 정의하는데 사용하는 개념인데 아래와 같은 형식으로 작성된다.
interface ISometing {
prop1: string;
prop2: number;
prop3?: boolean;
}
ISomething
은 인터페이스의 이름이다.
(나는 개인적으로 인터페이스의 이름을 만들때 맨앞에 대문자I를 붙히는걸 선호하는데, interface라는걸 이름만 보고도 알 수 있게 하고 싶어서 그렇다)
그리고 이 ISomething
이라는 인터페이스 내부에는 prop1, prop2, prop3이라는 속성이 정의되고, 각 속성에는 이름
과 타입
을 갖고 있고, 동시에 ?를 사용해 prop3과 같이 선택적으로 해당 속성이 존재할수도 있고 안할수도 있다.
그럼 해당 인터페이스를 어떤식으로 사용하느냐?
const something:ISomething = {
prop1: "hello",
prop2: 100
}
이런식으로 사용할 수 있는데, ISomething이 정의된것을 살펴보면 prop1, prop2는 ?가 붙지 않았기 때문에 무조건 구현이 되어야하는 속성이고, ?가 붙은 prop3은 optional하게 구현이되면 된다.
언뜻 보기에는 type
이랑 interface
가 서로 비슷비슷해보이는데 둘의 차이점도 알아보자.
extends
키워드를 사용해 확장할 수 있다.
interface IPerson {
name: string;
age: number
}
interface IStudent extends IPerson {
college: string;
}
const me: IStudent = {
name: "Hyeon",
age: 30,
college: "HY"
}
&
기호를 이용해 확장할 수 있다.
type TPerson = {
name: string;
age: number;
}
type TStudent = TPerson & {
college: string;
}
const me: TStudent = {
name: "Hyeon",
age: 30,
college: "HY"
}
선언적 확장이 가능한데, 이게 무슨말이냐? 같은 이름으로 한번 더 선언하면 자동으로 확장이 된다는 소리임
interface IPerson{
name: string;
age: number;
}
interface IPerson {
gender: string;
}
const me: IPerson = {
name: "Hyeon",
age: 30,
gender: "male"
}
그럼 이게 좋은건가? 그건 잘 모르겠다.
개인적으로는 오히려 휴먼에러를 야기할 수 있다고 생각한다.
예를 들어서, 어떤 사람이 먼저 interface를 선언해서 사용하고 있다고 하자, 그 후 다른 사람이 똑같은 이름으로 Interface를 선언하면 에러가 나는게 아니라 확장이 될건데, 이는 구현의 의도와는 전혀 다른 상황이 일어날 수 있는 가능성이 있다고 생각해서 좋은지는 잘 모르겠다.
선언적 확장이 불가능하다.
따라서 객체의 확장성을 위해서는 interface
를 사용하는게 더 좋다.
type TPerson = {
name: string;
age: number;
}
type TPerson = { // ❗️Error: Duplicate identifier
gender: string
}
객체(오브젝트)의 타입을 설정할 때 사용할 수 있고, 원시 자료형에는 사용할 수 없다.
interface IPerson {
name: string;
age: number;
gender: string;
}
interface IName extends string {
// 불가능
}
객체 타입을 정의할때도 사용할 수 있지만, 객체 타입을 정의할때는 interface
를 사용하는게 좋고,
단순한 원시값이나 튜플, 유니온 타입을 선언할때는 type
을 사용하는게 좋다.
type name = string; // primitive 원시값
type age = number;
type person = [string, number, boolean]; // tuple
type numberAndString = number | string; // union
computed value 사용이 불가능하다.
type TSubjects = "math" | "science" | "sociology";
interface IGrades {
[key in TSubjects]: string; // ❗️Error: A mapped type may not declare properties or methods.
}
computed value 사용이 가능하다
type TSubjects = "math" | "science" | "sociology";
type TGrades = {
[key in TSubjects]: string;
}
정리
type
은 모든 타입을 선언할 때 사용할 수 있고,interface
는 객체에 대한 타입을 선언할 때만 사용할 수 있다.
또한 확장이 불가능한 타입을 선언하고 싶다면type
을, 확장이 가능한 타입을 선언하고 싶다면interface
를 사용하자.