클래스는 인터페이스를 통해 사용할 때가 많다
타입 별칭과 같이 인터페이스도 타입에 이름을 지어주는 수단으로 인터페이스를 사용하면 타입을 더 깔끔하게 정의할 수 있다
타입 별칭과 인터페이스는 문법만 다르고 거의 같은 기능을 수행한다
몇몇 부분에서만 차이를 보인다
type Sushi = {
calories: number
salty: boolean
tasty: boolean
}
interface Sushi {
calories: number
salty: boolean
tasty: boolean
}
둘 다 형태를 정의하며 두 형태 정의는 서로 할당할 수 있다 (실제로 둘은 같다)
여러 음식을 정의하기 위해 Food 라는 타입으로 고ㅜㅇ통된 정보를 정의하고 다른 음식들을 재정의 해보자
type Food = {
calories: number
tasty: boolean
}
type Sushi = Food & {
salty: boolean
}
type Cake = Food & {
sweet: boolean
}
위 코드를 인터페이스로도 똑같이 정의할 수 있다
interface Food {
calories: number
tasty: boolean
}
interface Sushi extends Food {
salty: boolean
}
interface Cake extends Food {
sweet: boolean
}
인터페이스는 객체 타입, 클래스, 다른 인터페이스 모두 상속 받을 수 있다
type A = number
type B = A | string
이와 같은 형태는 인터페이스로 작성할 수 없다
interface A {
good(x: number): string
bad(x: number): string
}
interface B extends A {
good(x: string | number): string
bad(x: string): string // error
}
인터페이스 B 에서 A 를 상속 시 타입이 매개변수 타입이 달라서 bad() 의 경우 에러가 발생한다
위 예에서 인터페이스를 타입 별칭으로 변경 후 extends를 인터섹션(&) 으로 변경하면 확장하는 타입을 조합하는 방향으로 동작한다
bad()를 오버로드한 시그니처가 만들어진다
declaration merging (선언 합침) 은 같은 이름으로 정의된 여러 정의를 자동으로 합치는 타입스크립트의 기능이다
interface User {
name: string
}
interface User {
age: number
}
위의 User 인터페이스는 다음과 같다
interface User {
name: string
age: number
}
한 편 인터페이스끼리는 충돌할 수 없다
오버라이드 되지 않는다
interface User {
name: string
}
interface User {
name: number // error
}
같은 인터페이스 내에서 한 번 선언된 name 프로퍼티는 다른 인터페이스에서도 동일한 타입을 가져야 한다
제네릭 선언 시 제네릭의 선언과 이름까지 똑같아야 한다
interface User<Age extends number>{
age: Age
}
interface User<Age extends string> {
age: Age
}
위 경우에도 extends 되고있는 타입이 다르기 때문에 에러가 발생한다
클래스 선언 시 implements 라는 키워드를 이용해
특정 인터페이스를 만족시킴을 표현할 수 있다
다른 명시적 타입 어노테이션 처럼 implements로 타입 수준의 제한을 추가하면 구현에 문제가 있을 시 쉽게 파악할 수 있다
디자인 패턴을 구현하는 대표적 방식이 되기도 한다
interface Animal {
eat(food: string): void
sleep(hours: number): void
}
class Cat implements Animal {
eat(food: string) {
//
}
sleep(hours: number) {
//
}
}
Cat 은 Animal 에서 선언된 모든 메소드를 구현해야 하며 프로퍼티나 메소드를 추가할 수 있다
인터페이스로 인스턴스 프로퍼티를 정의할 수 있지만
가시성 한정자 (private, protected, public)는 선언할 수 없으며 static 도 선언할 수 없다
인스턴스 프로퍼티를 readonly 로는 선언 가능
한 클래스가 여러 인터페이스를 구현할 수도 있다
class Cat implements Animal, Feline {}
모든 기능은 완전한 타입 안전성을 제공한다
인터페이스 구현은 추상 클래스 상속돠 비슷하다
하지만 인터페이스 구현은 가볍고 범용으로 쓰이지만
추상 클래스는 특별한 목적과 풍부한 기능을 갖는다
인터페이스는 형태를 정의하는 수단으로
값 수준에서 객체, 배열, 함수, 클래스, 클래스 인스턴스를 정의할 수 있다
아무런 자바스크립트 코드를 만들지 않고 컴파일 타임에만 존재한다
추상 클래스는 클래스만 정의할 수 있다
추상 크랠스는 런타임에 자바스크립트 클래스 코드를 만든다
추상클래스는 생성자와 기본 구현을 가질 수 있고 프로퍼티와 메소드에 접근 한정자를 지정할 수 있다
여러 클래스에서 공유하는 구현이라면 추상 클래스
단순히 클래스를 정의하는 것이라면 인터페이스 사용