타입 별칭과 동일하게 타입에 이름을 지어주는 문법이지만 차이점이 있다. 둘의 차이점은 아래 참고.
/** Interface */
interface Person {
name: string;
age: number;
sayHi: () => void;
sayBye(): void;
sayBye(a: number): void;
}
type Person2 = {
name: string;
age: number;
sayHi: () => void;
sayBye(): void;
sayBye(a: number): void;
} | number; // Union type possible
type UnionType = Person | number
const person: Person = {
name: "kihoon",
age: 25,
sayHi: () => {
console.log('hello');
},
sayBye: function (a?: number) {
console.log('bye', a);
}
};
const person2: Person | number = 1;
Person2의 경우 type alias를 통해 number타입과의 유니온 타입으로 정의하고 있는 것을 확인할 수 있다.UnionType처럼 별도로 alias를 통해 다시 정의하거나, 맨아래 person2처럼 변수 선언시에 유니온 타입으로 선언하는 수밖에 없다.sayHi의 경우)sayBye)의 경우
sayBye의 경우처럼 오버로딩을 사용하고자 하는 경우에는 반드시 시그니쳐 방식을 사용해야 한다. (표현식 방식을 사용할 경우 에러)person 변수 정의할때 sayBye 함수 정의 시 optional parameter를 사용해서 a?: number 로 구현하는 모습)I를 추가하여 식별자를 사용하는 경우도 흔히 있다고 하니 참고로 알아두자./** Extending Interface */
interface Animal {
name: string;
family: string;
age: number;
}
// type Animal = { // same
// name: string;
// family: string;
// age: number;
// }
interface Dog extends Animal {
family: "Canidae";
// family: 1 // error
barks: boolean;
}
interface Cat extends Animal {
family: "Felidae";
claws: boolean;
}
/** extending multiple classes */
// interface DogCat extends Dog, Cat {} // error
interface Wolf extends Dog {
howls: boolean;
}
interface WolfDog extends Dog, Wolf {}
const wolfDog: WolfDog = {
name: 'Pluto',
family: "Canidae",
age: 8,
barks: true,
howls: true,
}
extends 키워드를 사용하여 다른 객체를 확장하여 정의할 수가 있다.
extends하는데 사용할 수 있다는 이야기다)family 프로퍼티의 경우 Animal에서 string 타입으로 정의된 프로퍼티인데,Dog와 Cat에서 각각 “Canidae”, “Felidae”라는 스트링 리터럴 타입으로 특정해주고 있는 모습이다.
family: 1의 경우 number literal type은 string type의 subtype이 아니기 때문에 에러가 발생한다)WolfDog 인터페이스의 경우 Dog과 Wolf 객체 타입을 동시에 확장하고 있다.WolfDog 타입 변수인 wolfDog의 경우 Dog와 Wolf가 가지는 각각의 프로퍼티들을 모두 동시에 가지는 값을 할당받는 것을 볼 수 있다.(그렇지 않으면 에러 발생)CatDog의 경우, Cat과 Dog을 동시에 확장하려 하고 있으나, 사실 둘은 family 프로퍼티에 “Canidae”와 “Felidae” 라는 서로 다른 string literal type을 정의하고 있기 때문에, 교집합이 없는 서로소 관계이고 (둘의 family타입이 다르기 때문에 Cat타입이면서 Dog타입인 경우는 존재할 수 없다), 따라서 이 둘을 동시에 상속하는 자식 인터페이스를 만드는 것이 불가능한 것이다.Documentation - Declaration Merging
/** Declarization Merging */
interface Person {
name: string;
}
interface Person {
// name: number; // error - conflict
// name: "kihoon"; // error - also conflict. extends와 다르게subtype이어도 안된다.
// name: string; // 이렇게 같아야지만 가능. 하지만 굳이 이렇게 쓸 일이 있을까?
age: number;
}
const person: Person = {
name: "kihoon",
age: 25,
};
interface는 같은 식별자 이름으로 추가 정의가 가능하다. 추가 정의를 할 경우, merging이라고 하여 정의한 내용들이 합쳐지게 된다.
extends와 비슷하지만 다른 부분이 있다. 합치기(declaration merging)의 경우, 확장과는 다르게 기존 프로퍼티에 대한 타입 특정이(subtype이라고 하더라도) 불가능하다.