이 글은 아래 강의를 바탕으로 정리한 글입니다. 🤗
https://inf.run/UGoRu💡 인터페이스란 타입 별칭과 동일하게 타입에 이름을 지어주는 또다른 문법입니다.
특히 객체의 구조를 정의하는데 특화된 문법이기 때문에 일반적으로 객체 타입을 정의하는데에 많이 사용됩니다.
아래와 같이 인터페이스에서도 선택적 프로퍼티 설정이나 읽기 전용 프로퍼티 설정, 메서드 타입 정의(호출 시그니처 사용 권장, 메서드 오버로딩이 가능하기 때문)가 모두 가능합니다.
interface Person {
readonly name: string;
age?: number;
// sayHi: () => void;
// 함수 오버로딩을 구현할 때는 호출 시그니처 사용 권장
sayHi(): void;
sayHi(a: number, b: number): void;
}
type Type1 = number | string | Person;
type Type2 = number & string & Person;
const person: Person = {
name: "John",
// age: 30,
sayHi: () => {
console.log("Hi");
},
};
person.name
= "Jane"; // ❌ 오류 발생, name은 readonly 프로퍼티이므로 수정 불가
person.sayHi();
person.sayHi(1, 2);위 예시에서 보다시피 타입 별칭에서도 하던 것들 모두 interface에서도 설정 및 사용이 가능한데, 어떤 차이가 있는걸까요?
📌 type alias와 interface 간에는 몇가지 차이점이 존재하는데, 그 중 하나가 타입 별칭에서는 Union이나 Intersection 타입을 정의할 수 있었던 반면, 인터페이스에서는 할 수 없는 것 입니다.
type Type1 = number | string;
type Type2 = number & string;
interface Person {
name: string;
age: number;
} | number // ❌따라서 인터페이스로 만든 타입을 Union 또는 Intersection으로 이용해야 한다면 다음과 같이 타입 별칭과 함께 사용거나 타입 주석에서 직접 사용해야 합니다.
type Type1 = number | string | Person;
type Type2 = number & string & Person;
const person: Person & string = {
name: "이정환",
age: 27,
};💡 interface 확장이란 하나의 인터페이스를 다른 인터페이스들이 상속받아 중복된 프로퍼티를 정의하지 않도록 도와주는 문법입니다.
아래와 같이 interface 타입이름 extends 확장대상타입이름 형태로 정의하면 확장할 타입에 정의된 모든 프로퍼티를 다 가지고 오게 됩니다.
interface Animal {
name: string;
age: number;
}
// 확장 또는 상속을 위해 extends 키워드 사용
interface Dog extends Animal {
isBark: boolean;
}
interface Cat extends Animal {
// 상속받은 프로퍼티의 타입을 재정의할 수 있으나 원본 프로퍼티 타입의 서브 타입이어야 함.
// (예를 들어 name: number 는 불가능)
name: "hello"; // string 리터럴 타입은 string 타입의 서브 타입이므로 가능
isScratch: boolean;
}
interface Chicken extends Animal {
isFly: boolean;
}
const dog: Dog = {
name: "돌돌이",
age: 3,
isBark: true,
};
const cat: Cat = {
// name: "냐옹이", // ❌ 오류 발생, name에 string 리터럴 타입이 들어가 있기 때문
name: "hello",
age: 2,
isScratch: true,
};
const chicken: Chicken = {
name: "병아리",
age: 1,
isFly: false,
};✅ 이때, 확장 대상 타입인 Animal은 Dog의 슈퍼타입이 됩니다.
여러 개의 인터페이스를 확장하는 것 또한 가능합니다.
interface DogCat extends Dog, Cat {}
const dogCat: DogCat = {
name: "",
color: "",
breed: "",
isScratch: true,
};참고로 인터페이스는 인터페이스 뿐만 아니라 타입 별칭으로 정의된 객체도 할당할 수 있습니다.
type Animal = {
name: string;
color: string;
};
interface Dog extends Animal {
breed: string;
}📌 타입 별칭의 경우 동일한 이름을 부여하면 에러가 발생하지만 interface는 동일한 이름으로 중복 선언해도 오류가 발생하지 않습니다.
이유는 동일한 이름으로 중복 선언한 interface는 결국 합쳐지기 때문입니다.
interface Person1 {
name: string;
}
interface Person1 {
age: number;
}
const person1: Person1 = {
name: "John",
age: 30,
};💡 이러한 선언 합침은 일반적으로 간단한 프로그래밍엔 사용되지 않고
TS의 모듈(=라이브러리의 타입이 조금 부실할 경우) 보강에 주로 사용됩니다.
interface Lib {
a: number;
b: number;
}
const lib: Lib = {
a: 1,
b: 2,
// 대부분 라이브러리들은 이미 타입 정의가 끝나있기 때문에 임의로 프로퍼티 추가할 수 없음.
// 이런 경우 아래와 같이 interface 선언 합침을 사용
c: "hello",
};
interface Lib {
c: string;
}