저번 시간에는 class 를 만들 때 타입을 지정하는 방법을 알아보았습니다. 오늘은 Object 에 타입을 지정할 수 있는 interface 에 대해 알아보겠습니다.
type 키워드 말고도 interface 로 타입변수를 생성할 수 있습니다. object 타입을 지정할 시, type 키워드를 사용할 때 쓴 등호는 필요하지 않습니다.
interface Square {
color: string;
width: number;
}
let square: Square = { color: "red", width: 100 };
type vs interface 에 대해 비교해보기 전에 아래의 타입을 한 번 지정해봅시다.
let student = { name: "kim" };
let teacher = { name: "kim", age: 20 };
interface Studet {
name: string;
}
interface Teacher {
name: string;
age: number;
}
let student: Studet = { name: "kim" };
let teacher: Teacher = { name: "kim", age: 20 };
interface 의 장점은 extends 로 복사가 가능합니다. 중복되는 속성이 존재하는 경우 사용하며, 실제로 2번의 코드와 동일한 내용입니다.
interface Studet {
name: string;
}
interface Teacher extends Studet {
age: number;
}
let student: Studet = { name: "kim" };
let teacher: Teacher = { name: "kim", age: 20 };
type Animal = { name: string };
type Cat = { age: number } & Animal;
type vs interface 의 가장 큰 차이점은 중복선언 가능 여부입니다. interface 는 중복선언이 가능하고, type 은 중복선언이 불가능합니다. 외부 라이브러리 같은 경우 interface 를 많이 쓰기 때문에, 추후에 타입을 추가하는 것이 쉬워집니다. 다른 사람이 내 코드를 많이 이용할 것 같다면 object 타입을 정할 때 interface 를 사용하는 것이 좋은 선택일 수 있습니다.
// 하나의 interface 로 합쳐짐
interface Student {
name: string;
}
interface Student {
score: number;
}
// 중복선언이 불가능함
type Animal = { name: string };
type Animal = { age: number };
만약 extends 를 사용할 때 중복 속성이 발생하면 어떻게 될까요? 속성이 호환되지 않아 에러가 발생합니다.
interface Student {
name: string;
}
interface Teacher extends Student { // 에러 발생
name: number;
}
그렇다면 type alias 에서 & 연산자로 중복 속성이 발생한다면 어떻게 될까요? 지난번에 다룬 적이 있지만, name 의 타입이 'never' 가 됩니다. 하지만, 아래의 단 두 줄만 작성했을 때는 에러를 발생시키지 않습니다. 변수를 선언하고, 타입을 지정한 순간에서야 에러를 발생시키기 때문에 어떻게 보면 interface 를 사용하는 것이 더 안전하다고 볼 수 있습니다.
type Animal = { name: string };
type Cat = { name: number } & Animal;
let cat: Cat = { name: "kim" }; // 에러 발생
예제로 interface 를 이용해서 간단한 타입을 만들어봅시다.
let product = { brand: "Samsung", serialNumber: 1360, model: ["TV", "phone"] };
interface Product {
brand: string;
serialNumber: number;
model: string[];
}
let product: Product = {
brand: "Samsung",
serialNumber: 1360,
model: ["TV", "phone"],
};
쇼핑몰 장바구니를 구현하려고 하는데 array 안에 object 여러 개가 필요합니다. 역시 interface 를 이용해서 타입을 지정해 봅시다.
let basket = [
{ product: "청소기", price: 7000 },
{ product: "삼다수", price: 800 },
];
interface Basket {
product: string;
price: number;
}
let basket: Basket[] = [
{ product: "청소기", price: 7000 },
{ product: "삼다수", price: 800 },
];
갑자기 서비스가 업데이트되어 일부 상품은 card 속성이 들어가야 한다고 생각해봅시다. 위에서 만든 interface 를 extends 해봅시다.
{ product: "청소기", price: 7000, card: false }
interface Basket {
product: string;
price: number;
}
interface extedBaseket extends Basket {
card: boolean;
}
object 안에 함수를 2개 넣고 싶다고 가정하고, interface 를 이용해 object에 타입 지정을 해봅시다.
a. 이 object 자료는 plus() 함수를 내부에 가지고 있으며, plus 함수는 파라미터 2개를 입력하면 더해서 return 해줍니다.
b. 이 object 자료는 minus() 함수를 내부에 가지고 있으며, minus 함수는 파라미터 2개를 입력하면 빼서 return 해줍니다.
interface Confidence {
plus: (a: number, b: number) => number;
minus: (a: number, b: number) => number;
}
let data: Confidence = {
plus(a, b) {
return a + b;
},
minus(a, b) {
return a - b;
},
};
지금까지 Object 에 타입을 지정할 수 있는 interface 에 대해 알아보았습니다. 다음 시간에는 함수에서 rest 파라미터, destructing 할 때 타입을 지정하는 방법을 알아보겠습니다.