타입스크립트의 interface 키워드는
두개의 시스템 상호간의 약속 또는 규칙
을 의미한다.
틀, 설계도 라고 생각하면 쉽다.
함수나 객체가 일정한 '틀'을 가진다면, interface 를 통해
일관적인 '틀' 의 규격을 맞추어 예상 가능한 객체나 함수를 만들 수 있도록 도움을 준다.
interface 는 다음과 같은 범주에 대해 약속을 정의할 수 있다.
1. 객체의 형태 정의
interface Car {
make: string;
model: string;
year: number;
}
const myCar: Car = {
make: 'Toyota',
model: 'Corolla',
year: 2005
};
2. 함수의 형태 정의
interface GreetFunction {
(name: string, age: number): string;
}
const greet: GreetFunction = (name, age) => {
return `Hello ${name}, you are ${age} years old.`;
};
3. class
interface Animal {
name: string;
species: string;
sound(): void;
}
class Dog implements Animal {
name: string;
species: string;
constructor(name:string, species:string = "Dog"){
this.name = name;
this.species = species;
}
sound(): void {
console.log("멍")
}
}
const 멍멍이:Animal = new Dog("멍멍이")
멍멍이.sound();
클래스가 특정 조건을 충족하도록 강제할 수 있다.
implement 키워드를 사용한다.
멍멍이 class 는 반드시 Animal interface 에 명시된 속성과 메소드를 가져야만 한다.
interface User {
name: string;
age: number;
email?: string;
}
const Soo: User = {
name: 'soo',
age: 20
}
const Woo: User = {
name: "Woo",
age: 21,
email: "abc@gamil.com"
}
interface 에 '?' 를 붙혀서 선언해 주는 것으로
프로퍼티를 선택적으로 만들 수 있다.
User interface 를 받는 객체는 name, age 프로퍼티를 필수로 갖지만
email 프로퍼티는 선택적으로 설정할 수 있다.
값의 속성이 "읽기 전용" 이라는 것을 명시해준다.
컴파일 단계에서
초기화 이후에 값을 변경할 수 없다는 것을 명시해 주기 위한 옵션.
interface ReadonlyPerson {
readonly name: string;
readonly age: number;
}
let p1: ReadonlyPerson = { name: 'John', age: 30 };
p1.name = "jon" // 읽기 전용 속성이므로 'name'에 할당할 수 없습니다.
배열을 선언할 때 ReadonlyArray<T>
타입을 사용해 읽기 전용 배열을 생성 할 수도 있다.
let arr: ReadonlyArray<number> = [1,2,3];
arr.push(4) // readonly number[] 형식에 'push' 속성이 없습니다.
type alias 는 '타입 별칭' 이라는 이름으로 쓰인다.
기존의 타입에 새로운 이름을 지정할 수 있는 방법.
가장 직관적으로 확인할 수 있는 type alias 가 interface 에 대비되는 장점은
VSCode 로 확인할 수 있다.
interface 와 type alias 모두 "{} 형식에 ~ 형식의 ~ 속성이 없습니다"
하는 에러 메시지를 출력하지만 interface 는 해당 타입이
어떠한 구조를 가지고 있는지 보여주지는 않는다.
두 유형 모두 자동완성 기능은 제공한다.
둘의 특징은 다음과 같다.
interface
type alias
둘은 비슷하지만 다음과 같은 차이점을 가지고 있다.
interface A {
a:number,
b:number,
c:number
}
interface A {
d: number
} // 에러를 출력하지 않음
type B = {
a: number,
b: number,
c: number
} // "B" 식별자가 중복되었습니다.
type B = {
d: number
} // "B" 식별자가 중복되었습니다.
interface A {
a:number,
b:number,
c:number
}
interface Aa extends A {
d: number
}
type B = {
a: number,
b: number,
c: number
}
type Bb = B & {
d: number
}
type Jobs = 'salary worker' | 'retired';
interface Client {
name: string;
}
interface MoreJobs extends Jobs {
description: string;
} // 인터페이스는 개체 형식 또는 정적으로 알려진 멤버가 포함된 개체 형식의 교집합만 확장할 수 있습니다.ts(2312)
type VIPClient = Client & { benefits: Jobs};
정리
둘은 비슷하지만 대체할 수 없는 몇가지의 기능이 있다.
예를들어 선언 병합의 기능을 수행할 수 없는 type alias 만으로는
기존의 라이브러리의 타입을 확장하는 등의 기능을 수행하기 까다롭다.
반면에 조건부 타입, 타입가드 등의 고급 타입 등의 기능을 사용하여
보다 정제된 타입 시스템을 구축하는 것은 interface 만으로는 불가능하다.
요즘 추세는 type alias 를 default 로 사용하되, 필요에 따라 interface 를 이용한
확장을 추가하는 편이라고 한다.