interface는 객체의 모양을 정의하기 위하여 사용된다.
기존에는 type 키워드를 사용하여 객체의 모양을 정할 수 있었다.
type을 사용하는 것과 interface를 사용하는 것의 차이는 다음과 같다.
type Cafe = {
name: string
}
interface Cafe {
name: string
}
const starbucks : Cafe = {
name: 'starbucks',
}
거의 차이가 없으며 사용하는 것도 같다. 필요에 따라 골라쓸 수 있다.
interface에서 상속을 구현할 때는 클래스처럼 extends를 사용하며 type에서 상속을 구현할 때는 &를 이용하여 구현할 수 있다.
type Cafe = {
name: string;
}
type Starbucks = Cafe & {
}
interface Cafe {
name: string;
}
interface Starbucks extends Cafe {
}
const starbucks: Starbucks = {
name: "starbucks",
}
interface의 type과 다른 특징은 여러 번 선언하여 하나로 합칠 수 있다는 것이다.
interface Cafe {
name: string
}
interface Cafe {
discount: number
}
const starbucks: Cafe = {
name: "starbucks",
discount: 10
}
위와 같이 같은 이름의 interface를 여러 번 선언하게 되면 합쳐서 하나의 interface로 인식한다.
즉, Cafe는 name과 discount 속성을 가진 interface가 된다.
반면, 같은 이름의 type을 여러 번 선언하게 되면 에러가 발생한다.
interface 대신 type을 쓸 수 있는 것처럼, 인터페이스도 타입처럼 쓰일 수 있다.
interface Cafe {
name: string
}
function hello(cafe: Cafe): Cafe{
return {
name: 'starbucks'
}
}
hello({
name: 'starbucks'
})
hello 함수에서 인자 타입과 리턴 타입으로 Cafe 인터페이스가 사용되었다.
클래스가 아닌 타입처럼 사용하는 인터페이스이기 때문에, 리턴할 때 new를 사용해 인스턴스를 만들어 리턴하는 것이 아닌 인터페이스의 모습대로만 리턴해주면 되는 것을 주목해보자.
인터페이스는 클래스처럼 속성과 메소드를 가질 수 있지만, 인스턴스는 가질 수 없는 특성을 가지고 있다. 이는 추상 클래스와 유사한 것 같은데, 추상 클래스와 어떤 점이 다를까?
먼저, 추상 클래스의 코드를 살펴보면 추상 클래스를 extends를 사용하여 클래스를 상속하고 있다.
abstract class Cafe {
constructor(
public name: string
) {}
abstract hello();
}
class Starbucks extends Cafe {
constructor(name: string) {
super(name);
}
hello() {
console.log("hello");
}
}
반면, 인터페이스를 사용하는 코드에서는 implements를 통해 인터페이스를 상속하여 구현한다.
인터페이스에는 생성자를 만들 수 없다. 그래서 인터페이스를 상속하는 Starbucks 클래스의 생성자에서 name을 선언 및 초기화하고 있다.
또, 인터페이스의 속성들에는 접근제한자를 설정할 수 없다. 그러므로 인터페이스를 상속할 때 속성을 private나 protected로 만들 수가 없다.
interface Cafe {
name: string,
hello()
}
class Starbucks implements Cafe {
constructor(
public name: string
) {}
hello() {
console.log("hello");
}
}
모든 타입스크립트 코드는 먼저 자바스크립트로 변환된 후, 실행된다는 것을 기억해야 한다.
interface의 경우 자바스크립트에 존재하지 않는 것이기 때문에 자바스크립트로 변환했을 때, abstract와 다르게 interface 부분의 코드가 존재하지 않는다. 이는 코드가 더 가볍다는 것을 의미한다.
여러 개의 interface를 한 번에 상속할 수도 있다. implements 뒤에 상속할 인터페이스들을 모두 적으면 된다.
interface Cafe {
coffee: string
}
interface Bakery {
bread: string
}
class Dunkin implements Cafe, Bakery {
constructor(
public coffee: string,
public bread: string
) {}
}
const dunkin: Dunkin = {
coffee: '아메리카노',
bread: '도넛'
}