인터페이스는 Type과 비슷한 구조이다.
우선, player라는 타입을 만든다고 가정해보자.
type Player -= {
nickname: string,
healthBar: number
}
const onve : Plyaer = {
nickname: "onve",
healthBar: 10
}
아니면 이런 방식의 선언도 가능하다.
type Food = string;
또한, 타입이 특정 옵션들만 가지도록 만들 수도 있다.
type Tema: "red" | "blue" | "yellow"
type Player = {
nickname: string,
team: Team // 팀은 오직 red, blue, yellow만 가능하다.
}
그렇다면 인터페이스는 어떨까?
우선 type을 interface로 바꿔도 어떤 문제도 발생하지 않는다.
interface Player {
nickname: string,
team: Team
}
하지만 인터페이스는 오직 한가지의 역할만 가지고 있다.
바로 오브젝트의 모양을 결정해주는 것이다.
따라서 타입보다는 인터페이스를 쓸 때 사용하는 방식이 제한된다.
interface Team: string // Error
User interface를 만들어보자
interface User {
name: string
}
interface Player extends User {
}
const onve: Player = {
name: "onve"
}
타입과 사용법이 모두 똑같다. "="만 제외하면 모두 동일하다.
추상 클래스를 생각해보자.
abstract class User = {
constructor(
protected firstName: string,
protected lastName: string
) {}
abstract sayHi(name: string): string
abstract fullNameI(): string
}
class Player extends User {
fullName() {
return '${this.firstName} ${this.lastName}'
}
sayHi(name: string) {
return 'Hello ${name}. My name is ${this.fullName()}'
}
}
이와 같이 추상 클래스와 추상 메소드를 사용할 수 있었다.
하지만 이런 경우, TS가 자동으로 JS로 변경시킬 때 문제가 발생한다.
위의 코드를 JS로 변환시킨다면, 다음과 같다.
class User {
constructor(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
}
class Player extends User {
fullName() {
return '${this.firstName} ${this.lastName}'
}
sayHi(name: string) {
return 'Hello ${name}. My name is ${this.fullName()}'
}
}
이와 같이, 원하지 않는 User 클래스가 JavaScript 코드에 들어가게 되는 것이다.
이러한 상황을 막고자, 우리는 interface를 사용할 수 있다.
interface는 가벼워서, JS코드에 들어가지 않고 TS -> JS 단계에서 사라진다.
하지만 interface는 오직 TS에 오브젝트의 모양을 보내주는 역할만 한다.
따라서 abstract class 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() {
return '${this.firstName} ${this.lastName}'
}
sayHi(name: string) {
return 'Hello ${name}. My name is ${this.fullName()}'
}
}
위의 코드를 보면, interface는 Call Signature를 정해줌으로써 추상 메소드를 넣을 수 있다.
그리고, 한가지 더 중요한 점은 extends 대신 implements를 사용한다는 점이다.
그리고 이때, class내의 내부 프로퍼티는 모두 public으로 지정해야 한다.
implements는 TS에만 있는 것으로써 위의 코드를 JS로 변환할 때 다음과 같이 만들어준다.
class Player {
constructor(
public firstName: string,
public lastName: string
) {}
fullName() {
return '${this.firstName} ${this.lastName}'
}
sayHi(name) {
return 'Hello ${name}. My name is ${this.fullName()}'
}
}
바뀐 JS 코드가 많이 간단해진것을 알 수 있다.
*본 내용은 노마드코더 "Typescript로 블록체인 만들기"에서 습득한 내용을 바탕으로 재구성한 것 입니다.