인터페이스는 약속 또는 규칙을 의미한다. 사용하는 코드에 대해서 여러 규칙들을 정의할 수 있는데, 이를 인터페이스라고 한다.
밑의 코드를 보자. printLabel
이라는 함수는 labeledObj
라는 객체를 받는다. 이 때 해당 객체 안의 string
타입의 label
이라는 속성을 가져야 한다.
function printlabel(labelObj: {label: string}) {
console.log(labelObj.label)
}
let myObj = {size: 10, label: 'Size 10 Object'}
printlabel(myObj) // 'Size 10 Object'
이를 string 타입의 label 속성을 가진 인터페이스로 재작성 할 수 있다.
**interface LabeledValue** {
label: string;
}
function printlabel(labelObj: **LabeledValue**) {
console.log(labelObj.label)
}
let myObj = {size: 10, label: 'Size 10 Object'}
printlabel(myObj)
첫 번째 코드와 다른 것은 없지만, 인터페이스 안에 객체의 속성들에 대한 요구 조건을 넣어둠으로써 재사용성이 가능해진다.
인터페이스 안에 정의되어 있는 속성이 100% 다 일치해야 하는 것은 아니다. 선택적으로 속성을 사용할 수도 있다. 이를 옵션 속성이라 한다.
interface CraftBeer {
name: string;
hop?: number;
}
let myBeer = {
name: 'Saporo'
}
function brewBeer(beer: CraftBeer) {
console.log(beer.name)
}
brewBeer(myBeer)
위 코드에서 myBeer라는 객체 안에 hop이라는 속성이 존재하지 않아도 괜찮다. CreaftBeer 인터페이스에서 hop을 옵션 속성으로 주었기 때문이다.
하지만 아래와 같이 선언되어져 있는 속성에 잘못된 타입을 선택했거나
interface CraftBeer {
name: string;
**hop?: number;**
}
let myBeer = {
name: 'Saporo',
**hop: 'jasmin'**
}
function brewBeer(beer: CraftBeer) {
console.log(beer.name) // Error: Types of property 'hop' are incompatible.
}
brewBeer(myBeer)
인터페이스 내에 존재하는 속성이 아닌 경우
interface CraftBeer {
name: string;
hop?: number;
}
let myBeer = {
name: 'Saporo',
}
function brewBeer(beer: CraftBeer) {
console.log(beer.sample) // Error: Property 'sample' does not exist on type 'CraftBeer'.
}
brewBeer(myBeer)
혹은 오탈자가 발생한 경우
interface LabeledValue {
label: string;
}
function printlabel(labelObj: LabeledValue) {
console.log(labelObj.lavel) // Error: Property 'lavel' does not exist on type 'LabeledValue'. Did you mean 'label'?
}
let myObj = {size: 10, label: 'Size 10 Object'}
printlabel(myObj)
에러를 발생시키게 된다.
따라서 인터페이스 내에 존재하지 않는 속성에 접근하거나 오탈자가 발생했을 때 그 문제를 지적해 줄 수 있다는 것이 옵션 속성의 장점이다(근데 존재하지 않는 속성에 대해서는 옵션 속성을 사용하지 않아도 작동하는 거 같기도..)