2024년 2월 26일 작성
TypeScript Interface Type - 객체 계약서
TypeScript의 Interface는 객체가 가져야 할 구조와 type을 정의하는 데 사용되며, 객체의 property와 method를 명시하여 객체의 일관성을 유지할 수 있도록 합니다.
Interface : 객체 계약서
- TypeScript의 interface는 변수, 함수, class가 특정 구조와 type을 갖추도록 명시하는 데 사용됩니다.
- 여러 type의 property로 이루어진 새로운 type을 정의하는 것과 같습니다.
- interface에 선언된 property 또는 method의 구현을 강제하여 일관성을 유지할 수 있도록 합니다.
- interface는 객체가 구현해야 할 구체적인 사항을 지정하고, 지키도록 강제합니다.
- 여러 type의 property로 이루어진 새로운 type을 정의하는 것과 같습니다.
- interface는 compile time에 구조와 type을 검사하기 위해 사용되며, runtime에는 제거됩니다.
- TypeScript file이 compile된 JavaScript file에는 interface에 대한 code가 없습니다.
- JavaScript ES6는 interface를 지원하지 않지만, TypeScript는 interface를 지원합니다.
- TypeScript는 interface를 통해 개발자가 더 명확하고 유지 보수가 용이한 code를 작성할 수 있도록 합니다.
변수와 Interface
- interface는 변수의 type으로 사용할 수 있습니다.
- interface를 type으로 선언한 변수는 해당 interface를 준수하여야 합니다.
- interface를 정의하는 것은 새로운 type을 정의하는 것과 유사합니다.
interface Todo {
id: number;
content: string;
completed: boolean;
}
// 변수 'todo'의 type으로 'Todo' interface를 선언함
let todo: Todo;
// 변수 todo는 Todo interface를 준수해야 함
todo = { id: 1, content: 'typescript', completed: false };
- interface를 사용하여 함수 parameter의 type을 선언할 수 있습니다.
- 해당 함수에는 함수 parameter의 type으로 지정한 interface를 준수하는 인수를 전달해야 합니다.
- 함수에 객체를 전달할 때 복잡한 매개 변수 검사 과정이 필요 없어서 매우 유용합니다.
interface Todo {
id: number;
content: string;
completed: boolean;
}
let todos: Todo[] = [];
// parameter 'todo'의 type으로 'Todo' interface를 선언함
function addTodo(todo: Todo) {
todos = [...todos, todo];
}
// parameter 'todo'는 'Todo' interface를 준수해야 함
const newTodo: Todo = { id: 1, content: 'typescript', completed: false };
addTodo(newTodo);
console.log(todos); // [ { id: 1, content: 'typescript', completed: false } ]
함수와 Interface
- interface는 함수의 type으로 사용할 수 있습니다.
- 함수의 interface에는 type이 선언된 parameter list와 return type을 정의합니다.
- 함수 interface를 구현하는 함수는 interface를 준수하여야 한다.
interface SquareFunc {
(num: number): number;
}
// 함수 interface를 구현하는 함수는 interface를 준수해야 함
const squareFunc: SquareFunc = function (num: number) {
return num * num;
}
console.log(squareFunc(10)); // 100
Class와 Interface
- class 선언문의
implements
뒤에 interface를 선언하면, 해당 class는 지정된 interface를 반드시 구현해야 합니다.- 이로써 interface를 구현하는 class들은 일관성을 유지할 수 있게 됩니다.
- interface는 property와 method를 가질 수 있다는 점에서 class와 유사하나, 직접 instance를 생성할 수는 없습니다.
interface ITodo {
id: number;
content: string;
completed: boolean;
}
// 'Todo' class는 'ITodo' interface를 구현해야 함
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는 property뿐만 아니라 method도 포함할 수 있으며, 추상 class와 달리 모든 method는 추상 method이어야 한다.
- 추상 class는 추상 method와 일반 method 모두 가질 수 있습니다.
- interface를 구현하는 class는 interface에서 정의한 property와 추상 methdo를 반드시 구현해야 합니다.
interface IPerson {
name: string;
sayHello(): void;
}
// 'Person' class는 'IPerson' interface에서 정의한 property와 추상 method를 반드시 구현해야 함
class Person implements IPerson {
// interface에서 정의한 property 구현
constructor(public name: string) { }
// interface에서 정의한 추상 method 구현
sayHello() {
console.log(`Hello ${this.name}`);
}
}
function greeter(person: IPerson): void {
person.sayHello();
}
const me = new Person('Lee');
greeter(me); // Hello Lee
비슷하지만 다른 Interface와 추상 Class
- interface와 추상 class(abstract class)는 method, property의 구조와 type을 강제하고, 추상 method(구현 없이 선언만 한 method)를 가진다는 점에서 비슷하지만, 몇 가지 다른 점이 있습니다.
Interface | Abstract Class |
---|---|
주로 type check를 위해 사용됩니다. 객체의 구조를 정의하며, 이 구조에 따라 객체가 형성되어야 함을 명시합니다. |
구현과 상속을 위해 사용됩니다. 일부 기능을 구현하고, 나머지 기능은 상속받는 class에서 구현하도록 강제할 수 있습니다. |
property과 method의 signature(추상 method 등)만을 정의할 수 있으며, 구현을 포함할 수 없습니다. | 추상 method뿐만 아니라 구현(일반 method 등)도 포함할 수 있습니다. |
class는 여러 interface를 구현(implement)할 수 있습니다. 이를 통해 다중 상속과 유사한 효과를 낼 수 있습니다. |
class는 하나의 추상 class만 상속(extend)할 수 있습니다. 이는 JavaScript와 TypeScript에서 다중 상속을 지원하지 않기 때문입니다. |
runtime에는 존재하지 않습니다. TypeScript를 JavaScript로 compile할 때 interface는 제거됩니다. |
runtime에도 존재합니다. compile 후에도 JavaScript code에 추상 class는 남습니다. |
특별한 keyword 없이 추상 method를 정의합니다. | abstract keyword를 사용하여 추상 method를 정의합니다. |
- 다중 상속이 필요하거나 type check만이 목적이라면 interface를, 구현을 공유하고 싶다면 추상 class를 사용하는 것이 좋습니다.
선택적 속성 (Optional Property)
- 선택적 속성(optional property)을 선언하여 interface의 property를 선택적으로 구현할 수 있습니다.
- interface의 일반적인 property는 반드시 구현해야 합니다.
- 선택적 속성은 property 이름 뒤에 물음표(
?
)를 붙이며, 구현을 생략해도 오류가 발생하지 않습니다.
interface UserInfo {
username: string;
password: string;
age?: number;
address?: string;
}
const userInfo: UserInfo = {
username: 'simin@gmail.com',
password: '123456'
}
console.log(userInfo);
Interface 상속 (Interface 확장)
- interface는
extends
keyword를 사용하여 interface 또는 class를 상속받을 수 있습니다.
interface Person {
name: string;
age?: number;
}
interface Student extends Person {
grade: number;
}
const student: Student = {
name: 'Lee',
age: 20,
grade: 3
}
- 복수의 interface를 상속받을 수도 있습니다.
interface Person {
name: string;
age?: number;
}
interface Developer {
skills: string[];
}
interface WebDeveloper extends Person, Developer {}
const webDeveloper: WebDeveloper = {
name: 'Lee',
age: 20,
skills: ['HTML', 'CSS', 'JavaScript']
}
- interface는 interface뿐만 아니라 class도 상속받을 수 있습니다.
- 이때 class의 모든 member(
public
,protected
,private
)가 상속되지만, 구현까지 상속하지는 않습니다.
class Person {
constructor(public name: string, public age: number) {}
}
interface Developer extends Person {
skills: string[];
}
const developer: Developer = {
name: 'Lee',
age: 20,
skills: ['HTML', 'CSS', 'JavaScript']
}