
TypeScript에서 인터페이스(Interface)는 일반적으로 타입 체크를 위해 사용이 된다.
인터페이스는 변수, 함수, 클래스에 사용할 수 있으며, 인터페이스에 선언된 프로퍼티 또는 메서드의 구현을 강제하여 일관성을 유지하도록 한다.
JavaScript는 인터페이스를 따로 지원하지 않지만, TypeScript는 인터페이스를 지원한다. TypeScript의 예약어인 interface를 사용하여 TypeScript 인터페이스를 생성할 수 있다.
TypeScript에서 인터페이스는 객체(Object)의 구조를 정의하기 위해 주로 사용되는 예약어이다.
인터페이스를 만들 때 예약어를 작성하고, 인터페이스의 이름을 대문자로 작성한다. (네이밍 컨벤션: 이름을 짓는 일종의 관례)
interface User {
name: string;
age: number;
}
// 정상적으로 선언 됨.
const user: User = {
name: "anna",
age: 20
}
// 프로퍼티의 순서를 지키지 않아도 정상적으로 선언 됨.
const user: User = {
age: 20,
name: "anna"
}
// 정의된 프로퍼티보다 적게 작성했기 때문에 에러가 난다.
const user: User = {
name: "anna"
}
// 정의된 프로퍼티보다 많이 작성했기 때문에 에러가 난다.
const user: User = {
name: "anna",
age: 20,
job: "developer"
}
인터페이스를 사용하여 변수를 선언할 때는 반드시 정의된 프로퍼티를 전부 작성해야 한다.
또한 interface로 정의된 속성만 지정할 수 있으며, 그 외 프로퍼티를 추가로 작성하고자 해도 인터페이스 내에 정의되어 있지 않기 때문에 추가로 프로퍼티를 더 작성하여 선언할 수 없다.
그러나 인터페이스 안의 모든 프로퍼티가 필요한 것은 아니며, 어떤 조건에서만 존재하거나 아예 없을 수도 있기 때문에 ? 연산자를 사용하여 선택적 프로퍼티를 작성할 수도 있다.
interface User {
name: string;
age?: number;
}
// 정상적으로 선언된다.
const user: User = {
name: "anna"
}
인터페이스를 사용하여 객체의 프로퍼티 이름과 타입을 정의하고, 함수의 매개변수 타입과 반환 타입도 정의할 수 있다.
interface User {
name: string;
age: number;
job: string;
}
interface Greeting {
(user: User, greeting: string): string;
}
const greet: Greeting = (user, greeting) => {
return `${greeting}, ${user.name}! Your job : ${user.job}.`;
}
const user: User = {
name: "anna",
age: 30,
job: "developer"
};
const message = greet(user, "Hi");
console.log(message);
Greeting 인터페이스는 User 타입과 문자열 타입을 매개변수로 받아 문자열 타입을 반환한다.
greet 함수는 Greeting을 사용하여 구현되었으며, user 객체와 문자열 "hi"를 전달인자로 전달받아 문자열을 반환한다.
Greeting 인터페이스에서 이미 greet의 매개 변수인 user와 greeting의 타입과 반환 타입이 작성되어 있기 때문에, greet 함수는 string 타입을 반환한다고 명시하지 않아도 되며, 매개 변수의 타입 또한 작성하지 않아도 된다.
클래스에서도 인터페이스를 사용할 수 있다.
아래 예시를 통해 사용법을 간단하게 알아보자.
interface Calculator {
add(x: number, y: number): number;
substract(x: number, y: number): number;
}
class SimpleCalculator implements Calculator {
add(x: number, y:number) {
return x + y;
}
substract(x: number, y: number) {
return x - y;
}
}
const caculator = new SimpleCalculator();
console.log(caculator.add(4, 9)); //13
console.log(caculator.substract(10, 5)); //5
Calculator 인터페이스는 add와 substract 메서드를 정의하고 있고, SimpleCaculator 클래스는 Calculator 인터페이스를 사용하여 작성했다.
Caculator 인터페이스를 사용하고 있기 때문에 SimpleCaculator 클래스 내에는 Calculator 인터페이스 내에 정의된 두 메서드를 반드시 작성해야 한다.
또한 클래스를 구현할 때 인터페이스에서 정의된 함수나 메서드의 매개변수 타입과 반환 값과 일치하도록 구현해야 하므로, 클래스 내부에서 해당 메서드의 매개변수 타입을 다시 한번 더 명시해 주지 않으면 컴파일 에러가 발생하게 된다.
// Todo 인터페이스를 작성
interface Todo {
id: number;
content: string;
isDone: boolean;
}
// Todo 인터페이스를 타입으로 받는 todos를 완성
let todos:Todo[] = [];
// Todo 인터페이스를 타입으로 받는 addTodo를 완성
function addTodo(todo:Todo):void {
todos = [...todos, todo];
}
// Todo 인터페이스를 타입으로 받는 newTodo를 완성
const newTodo: Todo = {
id: 1,
content: 'learn typescript',
isDone: false,
};
addTodo(newTodo);
console.log(todos);
JavaScript에서 클래스를 확장할 때 extends라는 키워드를 사용해 기존에 존재하던 클래스를 상속해 새로운 클래스를 정의할 수 있다.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
//Person 클래스를 extends 키워드를 사용해 상속하여 새로운 클래스인 Student를 정의했습니다.
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
console.log(`${this.name} is studying hard for the grade ${this.grade}.`);
}
}
인터페이스도 extends라는 키워드를 사용하여 기존에 존재하던 인터페이스를 상속해 확장이 가능!
이렇게 하면 기존에 존재하던 인터페이스의 프로퍼티를 다른 인터페이스에 복사하는 것을 가능하게 해 주며, 인터페이스의 재사용성을 높여준다.
interface Person {
name: string;
age: number;
}
interface Developer extends Person {
language: string;
}
const person: Developer = {
language: "TypeScript",
age: 20,
name: "Anna",
}
기존에 존재하던 Person 인터페이스를 extends 키워드로 상속해 새로운 인터페이스인 Developer를 만들고, Developer 인터페이스를 사용하여 person이라는 객체를 구현
이때, Developer 인터페이스는 Person 인터페이스를 상속하고 있으므로, Person 내부의 프로퍼티를 그대로 받아올 수 있다.
아래 예시처럼 여러 인터페이스를 상속받아 확장할 수도 있다.
interface FoodStuff {
name: string;
}
interface FoodAmount {
amount: number;
}
interface FoodFreshness extends FoodStuff, FoodAmount {
isFreshed: boolean;
}
const food = {} as FoodFreshness;
food.name = "egg";
food.amount = 2;
food.isFreshed = true;
/* 실습 1 */
interface User {
name: string;
age: number;
}
//Student 인터페이스를 작성
interface Student extends User {
grade: number;
}
//Student 인터페이스를 받는 kimcoding을 완성
//kimcoding의 이름은 김코딩이고, 나이는 20세이며, 학년은 1
const kimcoding: Student = {
name: '김코딩',
age: 20,
grade: 1,
};
console.log(kimcoding); // { name: '김코딩', age: 20, grade: 1 }