인터페이스는 객체의 구조를 설명하는데 사용한다. 클래스와는 다르게 interface는 객체의 blueprints로 사용되는 것이 아닌 사용자 정의 타입으로 사용한다. 객체의 구조를 타입으로 정의한다.
interface Person {
// name: string = "Max"; // interface는 initializer를 가질 수 없다는 에러를 띄운다.
name: string;
age: number;
//method도 추가할 수 있다. functionName(parameter1: type): return type;
greet(phrase: string): void;
}
let user: Person;
user = {
name: "Jin",
age: 11,
greet(phrase) {
console.log(phrase + this.name);
},
};
user.greet("안녕하세요 나는 ");
실제로 interface로 구현했던 Person을 type을 이용해 사용자 정의 타입으로 바꿔도 문법적 에러 없이 잘 컴파일, 실행된다.
type Person = {
name: string;
age: number;
greet(phrase: string): void;
}
그래서 type이 더 유연할 수 있지만, 객체의 구조를 설명할 때는 interface를 사용하는 것이 더 의미적으로 명확하다.
// 추상클래스는 단일 상속만 가능
abstract class Animal {
...구현부...
}
class Dog extends Animal {
...
}
// 인터페이스는 다중 상속 가능
interface Move {
move(): void;
}
interface Speak {
speak(text: string): void;
}
interface Actions extends Move, Speak {
sayMyName(): void;
}
class Human implements Actions {
move(): void {
console.log("move");
}
speak(text: string): void {
console.log(text);
}
sayMyName(): void {
console.log("sayMyname!");
}
}
//interface => Animal Interface내의 makesound, move모두 구현해야한다.
interface Animal {
makeSound(): void;
move(): void;
}
class Dog implements Animal {
makeSound(): void {
console.log("Woof!");
}
move(): void {
console.log("Moving...");
}
}
const myDog: Animal = new Dog();
myDog.makeSound(); // 출력: "Woof!"
myDog.move(); // 출력: "Moving..."
//abstract class
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("Moving...");
}
}
class Dog extends Animal {
makeSound(): void {
console.log("Woof!");
}
}
const myDog = new Dog();
myDog.makeSound(); // 출력: "Woof!"
myDog.move(); // 출력: "Moving..."
아래 코드의 경우 Human class가 Actions interface를 상속받았다. 그리고 Human 인스턴스를 생성하는데, 앞서 jack의 타입을 Actions라고 명시하는 것도 가능하다. 그 이유는 Human 객체는 결국 Actions 인터페이스에 기반한 것이기 때문이다.
class Human implements Actions {
move(): void {
console.log("move");
}
speak(text: string): void {
console.log(text);
}
sayMyName(): void {
console.log("sayMyname!");
}
}
let jack: Actions;
jack = new Human();
type(사용자 정의 타입)에서와 마찬가지로 interface 내에서도 readonly property를 사용할 수 있다. private, public은 지정할 수 없다. 객체가 초기화 된 이후에는 값을 변경할 수 없다.
interface Actions extends Move, Speak {
readonly actionNumber: number;
...
}
class Human implements Actions {
actionNumber = 3;
...
}
사용자 정의 함수 타입을 type 키워드를 이용해 정의할 수 있다.
type addNum1 = (n1: number, n2: number) => number;
interface를 이용해서 function type을 정의할 수 있다. interface는 객체의 구조를 정의하는데, 함수도 결국엔 객체이기 때문에 interface를 이용해 정의가 가능하다.
interface addNum2 {
(n1: number, n2: number): number;
}
type을 이용하는 것이 코드의 양도 적고 익명함수를 사용함에서 오는 혼란을 방지할 수 있지만 이를 알아두긴 해야한다.