인터페이스
인터페이스는 일반적으로 타입 체크를 위해 사용되며 변수, 함수, 클래스에 사용할 수 있다.
또한 인터페이스는 여러 가지 자료형을 갖는 프로퍼티로 이루어진 새로운 자료형을 정의하는 것과 유사하다.
ES6는 인터페이스를 지원하지 않지만 TypeScript는 인터페이스를 지원한다.
인터페이스는 프로퍼티와 메소드를 가질 수 없다는 점에서 클래스와 유사하나 직접 인스턴스를 생성할 수는 없고 모든 메소드는 추상 메소드이다.
단, 추상 클래스의 추상 메소드와 달리 abstract 키워드를 사용하지 않는다.
그럼 이제 본격적으로 인터페이스에 대해서 알아보자.
#1 변수와 인터페이스
// 인터페이스의 정의
interface Todo {
id: number;
content: string;
completed: boolean;
}
// 변수 todo의 타입으로 Todo 인터페이스를 선언
let todo : Todo;
// 변수 todo는 Todo 인터페이스를 준수해야 한다
todo = { id: 1, content: 'typescript', completed: true };
2. 인터페이스를 사용하여 함수 파라미터의 타입을 선언할 수도 있다.
이때 해당 함수에는 함수 파라미터의 타입으로 지정한 인터페이스를 준수하는 인수를 전달해야 한다.
함수에 객체를 전달할 때 복잡한 매개변수 체크가 필요 없기 때문에 매우 유용하다.
// // 인터페이스의 정의
interface Todo {
id: number;
content: string;
completed: boolean;
}
let todos: Todo[] = [];
// 파라미터 todo의 타입으로 Todo 인터페이스를 선언
function addTodo(todo: Todo) {
todos = [...todos, todo];
}
// 파라미터 todo는 Todo 인터페이스를 준수해야 한다
const newTodo: Todo = { id: 1, content: 'typescript', completed: true };
addTodo(newTodo);
console.log(todos); // [ { id: 1, content: 'typescript', completed: true } ]
#2 함수와 인터페이스
// 함수 인터페이스 정의
interface SquareFunc {
(num: number): number;
}
// 함수 인터페이스를 구현하는 함수는 인터페이스를 준수해야 함
const squqreFunc: SquareFunc = function (num : number) {
return num * num;
};
console.log(squqreFunc(10)); // 100
#3 클래스와 인터페이스
// 인터페이스 정의
interface ITodo {
id: number;
content: string;
completed: boolean;
}
// Todo 클래스는 ITodo 인터페이스를 구현해야 한다
class Todo implements ITodo {
constructor (
public id: number,
public content: string,
public completed: boolean
) { }
}
const todo = new Todo(1, 'TypeScript', true);
console.log(todo);
또한 프로퍼티뿐만 아니라 메소드도 포함할 수 있다.
단, 모든 메소드는 추상 메소드이어야 하며 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 추상 메소드를 만드시 구현해야 한다.
// 인터페이스 정의
interface IPerson {
name: string;
sayHello(): void;
}
// 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 프로퍼티와 추상 메소드를 반드시 구현해야 한다
class Person implements IPerson {
// 인터페이스에서 정의한 프로퍼티의 구현
constructor (public name: string) { }
// 인터페이스에서 정의한 추상 메소드의 구현
sayHello() {
console.log(`Hello ${this.name}`);
}
}
function greeter(person: IPerson): void {
person.sayHello();
}
const me = new Person('Lee');
greeter(me); // Hello Lee
#4 덕 타이핑
interface IDuck { // 1
quack(): void;
}
class MallardDuck implements IDuck { // 3
quack() {
console.log('Quack!');
}
}
class RedheadDuck { // 4
quack() {
console.log('q-uack!');
}
}
function makeNoise(duck: IDuck): void { // 2
duck.quack();
}
makeNoise(new MallardDuck()); // Quack!
makeNoise(new RedheadDuck()); // q-uack! // 5
/*
1. 인터페이스 IDuck은 quack 메소드를 정의했다
2. makeNoise 함수는 인터페이스 IDuck을 구현한 클래스의 인스턴스 duck을 인자로 전달받는다
3. 클래스 MallardDuck은 인터페이스 IDuck을 구현했다
4. 클래스 RedheadDuck은 인터페이스 IDuck을 구현하지는 않았지만 quack 메소드를 갖는다
5. makeNoise 함수에 인터페이스 IDuck을 구현하지 않은 클래스 RedheadDuck의 인슽언스를 인자로 전달하여도 에러 없이 처리된다
*/
TypeScript는 해당 인터페이스에서 정의한 프로퍼티나 메소드를 가지고 있다면 그 인터페이스를 구현한 것으로 인정한다.
이것을 '덕 타이핑' 또는 '구조적 타이핑' 이라고 한다.
인터페이스를 변수에 사용할 경우에도 덕 타이핑은 적용된다.
interface IPerson {
name: string;
}
function sayHello(person: IPerson): void {
console.log(`Hello ${person.name}`);
}
const me = { name: 'Lee', age: 19 };
sayHello(me); // Hello Lee
변수 me는 인터페이스 IPerson과 일치하지는 않지만 IPerson의 name 프로퍼티를 갖고 있으면 인터페이스에 부합하는 것으로 인정된다.
인터페이스는 개발 단계에서 도움을 주기 위해 제공되는 기능으로 자바스크립트의 표준이 아니다.
따라서 위 예제의 TypeScript 파일을 자바스크립트 파일로 트랜스파일링하면 인터페이스가 삭제된다.
#5 선택적 프로퍼티
interface UserInfo {
username: string;
password: string;
age? : number;
address? : string;
}
const userInfo: UserInfo = {
username: 'tommy',
password: '123'
};
console.log(userInfo);
이렇게 선택적 프로퍼티를 사용하면 사용 가능한 프로퍼티의 파악이 가능하기 때문에 코드를 이해하는데 수월하다.
'TypeScript' 카테고리의 다른 글
제네릭 (0) | 2019.08.28 |
---|---|
클래스 (0) | 2019.08.26 |
TypeScript 정적 타이핑 (0) | 2019.08.25 |
TypeScript??? (0) | 2019.08.24 |