본문 바로가기
프론트엔드/TS 공부

인터페이스(Interface)

by 학습하는 청년 2023. 7. 26.

최종 수정 : 2024-05-28

인터페이스(Interface)

타입에 이름을 지어주는 또 다른 문법이다. 또한 객체의 구조를 정의하는데 특화된 문법이다. 이에 따라, 상속 및 병합 등의 특수한 기능을 제공한다.

 

인터페이스(interface)라는 뜻은 '상호간에 약속된 규칙'이라는 뜻이다. 그래서 프론트엔드 개발과 백엔드 개발로 나누어 웹 애플리케이션을 만들 때, 서버에서 어떻게 데이터를 줄지 정하는 작업을 '인터페이스를 맞춘다'고 표현하기도 한다.
 

메서드 오버로딩


인터페이스로 타입을 정의할 수 있는 부분
1) 객체의 속성과 속성 타입
인터페이스의 타입과 맞지 않는 객체에 인터페이스를 지정한다면 에러가 발생한다.

interface Book {
 name: string;
 page: number;
}

let TypeScript: Book { name: '타입스크립트', page: 462 };

// Error
let JavaScript: Book { name: '자바스크립트', page: 734, hobby: '개발' };

 
2) 함수의 파라미터와 반환 타입
- 객체는 함수의 파라미터로도 사용되고 반환값으로도 사용될 수 있다.

interface Book {
 name: string;
 page: number;
}

function countPage(random: Book) {
 console.log(random.page);
}

let typescript = { name: '타입스크립트', page: 643 };
countPage(typescript); // 643

- 함수의 반환 타입을 인터페이스로 정의

interface Book {
 name: string;
 page: number;
}

function getBook(random: Book): Book {
 return random;
}

 
3) 함수의 스펙(파라미터 개수와 반환값 여부 등)
4) 배열과 객체를 접근하는 방식
5) 클래스
 
인터페이스의 옵션 속성
- 인터페이스로 정의된 객체의 속성을 선택적으로 사용
- 상황에 따라서 유연하게 인터페이스 속성의 사용 여부를 결정할 수 있다.

interface Book {
 name?: string;
 page: number;
}

function someBook(random: Book) {
 console.log(random.page);
}

let typescript = { page: 645 };
someBook(typescript); // 645

 
인터페이스의 확장
- 타입 정의를 확장시킬 수 있다.
- 상속 : 객체 간 관계를 형성하는 방법, 상위(부모) 클래스의 내용을 하위(자식) 클래스가 물려받아 사용하거나 확장하는 기법

interface Book {
 name: string;
 page: number;
}

interface Athor extnds Book {
 athor: string;
}

// 사실상 이런 인터페이스가 된 것과 같다.
interface Athor {
 name: string;
 page: number;
 athor: string;
}

let typescript: Athor = {
 name: '타입스크립트',
 page: 679,
 athor: 'teadyeong'
}

참고 사항
- 부모 인터페이스에서 상속받은 속성의 타입을 자식 인터페이스에서 다르게 정의하면 에러가 발생한다.
- 여러번 상속 할 수 있다.

 

다중 확장이 가능하다.


선언 병합

타입 선언과 달리 같은 이름의 인터페이스를 선언해도 오류가 발생하지 않으며, 합쳐진다. 두 인터페이스의 프로퍼티의 타입이 같을 때는 병합되지만, 다를 경우에는 충돌이 발생한다.

 

개발을 할 때보다는 라이브러리의 타입이 부실하여 추가할 때 주로 사용한다.

interface Person {
  name: string;
}

interface Person {
  name: string;
  age: number;
}

interface Developer extends Person {
  name: 'hello';
}

const person: Person = {
  name: '',
  age: 33,
};


 
인터페이스를 이용한 인덱싱 타입 정의
인덱싱 : 객체의 특정 속성을 접근하거나 배열의 인덱스로 특정 요소에 접근하는 동작

let person = {
 name: 'taeadyeong',
 age: 32
};
console.log(person['name']); // taedyeong

let books = ['A', 'B', 'C']'
console.log(books[0]); // A

 
1) 배열 인덱싱 타입 정의

interface BookList {
 [index: number]: string;
}

let books: BookList = ['A', 'B', 'C']

books[0] // A
books[1] // B

 
2) 객체 인덱싱 타입 정의

// 속성 이름 - 문자열
// 속성 값 - 숫자
interface BookPage {
 [name: string]: number; 
}

let book: BookPage = {
 typescript: 785
}

let page = book[typescript]; // 785
let page = book.typescript; // 785


// 속성 이름 - 문자열
// 속성 값 - 문자열

interface BookPage {
 [name: string]: string;
}

let book: BookPage = {
 typescript: '785',
}

let page = book['typescript']; // 785

속성 이름에 숫자나 - 등 특수 기호가 들어가면 '점표기법'으로는 접근할 수 없기 때문에 '대괄호 표기법' 방식으로 접근해야 한다.
 


인터페이스와 인터섹션의 가장 큰 차이점

인터섹션은 두 가지 이상의 타입을 한 번에 합칠 수 있다. 물론, 인터페이스도 가능하다. 그러나 좀 더 지저분한 느낌이다.

// Interface
interface Entity {
  id: string;
}

interface TimestampEntity extends Entity {
  createdAt: Date;
  updatedAt: Date;
}

interface User extends Entity {
  username: string;
  email: string;
}

// 타입 별칭
type Entity = {
  id: string;
  createdAt: Date;
  updatedAt: Date;
}

type User = Entity & {
  username: string;
  email: string;
}

대부분의 경우 Interface와 타입 별칭을 둘 다 사용할 수 있다. 하지만 되도록 Interface의 목적에 맞는 경우라면 Interface를 사용하는 게 좋다.

댓글