프론트엔드/TypeScript

[TypeScript] Interface에 대해서 알아보자

병걸 2023. 5. 23. 09:14

타임스크립트에서는 Interface가 있다. 아래의 예시 언어를 봐보자

type Player = {
  name: string;
  team: Team;
  health: Health;
};

interface Player {
  name: string;
  team: Team;
  health: Health;
}

위 코드처럼 type Player 와 interface Player 는 둘 다 타입스크립트에게 오브젝트의 모양에 대해서 설명하고 있습니다.

단, interface는 오브젝트의 모양을 설명할 때만 사용할 수 있습니다.

또한 Interface와 type은 상속할때 쓰는 방식이 다릅니다.

먼저 type은 상속할때 아래와 같은 문법을 활용하며

type User = {
  name: string;
};
type Player = User & {};
const bg: Player = {
  name: "bg",
};

Interface는 아래와 같은 문법을 활용합니다.

interface User {
  name: string;
}

interface Player extends User {}

const bg: Player = {
  name: "bg",
};

보기에 따라서 편하게 활용하면 됩니다.

 

왜 굳이 똑같은 기능을 활용하는데 interface를 따로 쓰게 될까? 아래의 코드를 봐보자

interface User {
  name: string;
}
interface User {
  lastname: string;
}

interface User {
  number: number;
}

const bg: User = {
  name: "bg",
  lastname: "Girl",
  number: 10,
};

interface는 위와 같은 코드를 수행할 수 있습니다. User에 추가적으로 속성에 타입을 추가할 수 있습니다.

하지만 type의 같은 경우에는

type User = {
  nmae: string;
};

type User = {
  lastnmae: string;
};

User는 오류가 뜨게 됩니다. 

즉 type 보다는 Interface가 조금 더 나은 합체 능력을 가지고 있습니다. 같은 인터페이스에 다른 이름을 가진 속성들을 쌓을 수 있게 됩니다.

 

Interface의 다른 이점은 다른곳에서도 나타난다.

abstract class User {
  constructor(protected firstName: string, protected lastName: string) {}
  abstract sayHi(name: string): string;
  abstract fullName(): string;
}
new User() // 동작하지 않는다.
class Player extends User {
  fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string) {
    return `Hello ${name}. My name is ${this.fullName()}`;
  }
}

위에 추상 클래스를 활용한 코드가 있습니다. 추상 클래스의 인스턴스(new User())은 따로 만들수는 없습니다.

 

interface User {
  firstName: string;
  lastName: string;
  sayHi(name: string): string;
  fullName(): string;
}
class Player implements User {
  constructor(public firstName: string, public lastName: string) {}
  fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string) {
    return `Hello ${name}. My name is ${this.fullName()}`;
  }
}

function makeUser(user: User): User {
  return {
    firstName: "bg",
    lastName: "girl",
    fullName: () => "xx",
    sayHi: () => "string",
  };
}

위 코드처럼 추상 클래스를 Interface로 변형할 수 있습니다. 변형하는 과정에서 implements라는 요소가 필요한데 implements는 클래스가 특정 인터페이스를 충족하는지 확인할 수 있습니다.클래스가 올바르지 못하다면 오류가 발생합니다. implements절은 클래의 유형이나 메서드는 전혀 변경하지 않습니다.