1. Introduction

인터페이스는 일반적으로 타입체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다. 인터페이스는 여러가지 타입을 갖는 프로퍼티로 이루어진 새로운타입을 정의하는 것과 유사하다. 인터페이스에 선언된 프로퍼티 또는 메소드의 구현을 강제하여 일관성을 유지할 수 있도록 하는 것이다. ES6는 인터페이스를 지원하지 않지만 TypeScript는 인터페이스를 지원한다.

인터페이스는 프로퍼티와 메소드를 가질수 있다는 점에서 클래스와 유사하나 직접 인스턴스를 생성할 수 없고 메소드는 추상 메소드 이다. 단, 추상 클래스의 추상 메소드와 달리 abstract 키워드를 사용하지 않는다.

2. 변수와 인터페이스

인터페이스는 변수의 타입으로 사용할 수 있다. 이때 인터페이스를 타입으로 선언한 변수는 해당 인터페이스를 준수하여야 한다. 이것은 새로운 타입을 정의하는 것과 유사하다.

// 인터페이스의 정의
interface Todo {
	id: number;
	content: string;
	completed: boolean;
}

// 변수 todo의 타입으로 Todo 인터페이스를 선언하였다.
let todo: Todo;

// 변수 todo 는 Todo 인터페이스를 준수하여야 한다.
todo = { id: 1, content: 'typescript', completed: false };

인터페이스를 사용하여 함수 파라미터의 타입을 선언할 수 있다. 이때 해당하는 함수 파라미터의 타입으로 지정한 인터페이스를 준수하는 인수를 전달하여야 한다. 함수에 객체를 전달할 때 복잡한 매개변수 체크가 필요없어서 매우 유용하다.

interface Todo {
	id: number;
	content: string;
	completed: boolean;
}

let todos: Todo[] = [];

// 파라미터 todo의 타입으로 Todo 인터페이스를 선언하였다.
const addTodo = (todo: Todo) => {
	todos = [...todos, todo];
}

// 파라미터 todo는 Todo 인터페이스를 준수하여야 한다.
const newTodo: Todo = { id: 1, content: 'typescript', completed: false };
addTodo(newTodo);
console.log(todos);

// [ { id: 1, content: 'typescript', completed: false } ]

3. 함수와 인터페이스

인터페이스는 함수의 타입으로 사용할 수 있다. 이때 함수의 인터페이스에는 타입이 선언된 파라미터 리스트와 리턴 타입을 정의한다. 함수 인터페이스를 구현하는 함수는 인터페이스를 준수하여야 한다.

// 함수 인터페이스의 정의
interface SquareFucn {
	(num: number): number;
}

// 함수 인터페이스를 구현하는 함수는 인터페이스를 준수하여야 한다.
const squareFunc: SquareFunc = (num: number) => {
	return num * num;
}

console.log(squareFuc(10));

4. 클래스와 인터페이스

클래스 선언문의 implements 뒤에 인터페이스를 선언하면 해당 클래스는 지정된 인터페이스를 반드시 구현해야 한다. 이는 인터페이스를 구현하는 클래스의 일관성을 유지할 수 있는 장접을 갖는다. 인터페이스는 프로퍼티와 메소드를 가질 수 있다는 점에서 클래스와 유사하나 직접 인스턴스를 생성할 수는 없다.

interface ITodo {
	id: number;
	content: string;
	completed: boolean;
}

class Todo implements ITodo {
	constructor (
		public id: number,
		public content: string,
		public completed: boolean,
	) { }
}

const todo = new Todo(1, 'Typescript', false);

console.log(todo);

인터페이스는 프로퍼티뿐만 아니라 메소드도 포함할 수 있다. 단, 모든 메소드는 추상 메소드이어야 한다. 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 추상 메소드를 반드시 구현해야 한다.

interface IPerson {
	name: string;
	sayHello(): void;
}

/*
인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 
추상 메소드를 반드시 구현해야 한다.
*/
class Person implements IPerson {
	// 인터페이스에서 정의한 프로퍼티의 구현
	constructor(public name: string) {}

	// 인터페이스에서 정의한 추상 메소드의 구현
	sayHello() {
		console.log(`Hello ${this.name}`);
	}
}

const greeter = (person: IPerson): void => {
	person.sayHello();
}

const me = new Person('Lee');
greeter(me); // Hello Lee

5. 덕 타이핑 (Duck typing)

주의해야 할 것은 인터페이스를 구현하였다는 것 만이 타입체크를 통과하는 유일한 방법은 아니다. 타입체크에서 중요한 것은 값을 실제로 가지고 있는 것이다. 이해가 어려울 수 있으므로 예를 들어 설명한다.

interface IDuck {  // 1
	quack(): void;
}

class MallarDuck implements IDuck {   // 3
	quack() {
		console.log('Quack!');
	}
}

class RedheadDuck {   // 4
	quack() {
		console.log('q~uak!');
	}
}

function makeNoise(duck: IDuck): void {   // 2
	duck.quak();
}

makeNoise(new MallardDuck());    // Quack!
makeNoise(new RedheadDuck());    // q~uack!    // 5
  1. 인터페이스 IDuck은 quack 메소드를 정의하였다.