본문 바로가기
언어/TypeScript

인터페이스

by seacode 2025. 4. 13.

인터페이스 기초

자바나 컴개론 등에서 배웠던 인터페이스와 동일하다.

객체가 A 인터페이스의 타입이다 라는 것은 해당 인터페이스의 메소드를 구현했다는 의미.

즉, 클래스나 객체가 어떤 멤버 변수와 메서드를 가져야 하는지 정의한 것을 인터페이스라고 한다.

 

다만, 타입스트립트의 interface 는 객체 타입 뿐만 아니라 아래에 대해서도 타입을 정의할 수 있다.

  • 객체의 스펙(속성과 속성의 타입)
  • 함수의 파라미터
  • 함수의 스펙(파라미터, 반환 타입 등)
  • 배열과 객체를 접근하는 방식
  • 클래스
let person = { name: 'Capt', age: 28 };

function logAge(obj: { age: number }) {
  console.log(obj.age); // 28
}
logAge(person); // 28

 위 함수의 파라미터는 객체이다. 이처럼 단순 타입 뿐만 아니라, 객체의 속성 타입까지  age:number 처럼 정의할 수 있다.

여기다가 인터페이스를 적용하면...

interface personAge {
  age: number;
}

function logAge(obj: personAge) {
  console.log(obj.age);
}
let person = { name: 'Capt', age: 28 };
logAge(person);

logAge 함수의 파라미터는 personAge 라는 타입을 가져야한다 라고 명시적으로 바뀌었다.

 

* 위 예시로 알 수 있지만, 인터페이스를 사용하면, 항상 인터페이스의 속성 개수와 인자로 받는 객체 속성 개수가 일치하지 않아도 되고, 속성 순서를 지키지 않아도 된다. 

 

옵션 속성

역할

1. 인터페이스 사용 시 속성을 선택적으로 적용

2. 인터페이스에 정의되어있지 않는 속성에 대해서 확실히 인지시킴

interface CraftBeer {
      name: string;
      hop?: number;
    }
    
    let myBeer = {
      name: 'Saporo'
    };
    function brewBeer(beer: CraftBeer) {
      console.log(beer.brewery); // 'CraftBeer' 형식에 'brewery' 속성이 없습니다.
    }
    brewBeer(myBeer);

 

읽기 전용 속성과 배열

읽기 전용 속성 : 인터페이스로 객체를 처음 생성할 때만 값을 할당하고, 이후 수정 불가.

- readonly 를 앞에 붙이면 됨.

interface CraftBeer {
  readonly brand: string;
}

let myBeer: CraftBeer = {
  brand: 'Belgian Monk'
};
myBeer.brand = 'Korean Carpenter'; // error!

읽기 전용 배열 : 배열 선언 시  ReadonlyArray<T> 를 쓰면 됨

let arr: ReadonlyArray<number> = [1,2,3];
arr.splice(0,1); // error
arr.push(4); // error
arr[0] = 100; // error

 

객체 선언과 관련된 타입 체킹

interface CraftBeer {
  brand?: string;
}

function brewBeer(beer: CraftBeer) {
  // ..
}
brewBeer({ brandon: 'what' }); // error: Object literal may only specify known properties, but 'brandon' does not exist in type 'CraftBeer'. Did you mean to write 'brand'?

- 인터페이스에는  brand 라고 되어있는데, 함수 파리미터로 넘겨주는데에서는 brandon 이라고 오타를 내서 오류가 남.

- 이런 류의 타입추론을 무시하려면 아래와 같이 as 를 사용할 수 있다.

let myBeer = { brandon: 'what' }';
brewBeer(myBeer as CraftBeer);

- 만약 인터페이스에서 정의하지 않은 속성을 추가로 사용하고 싶을 때는 any를 쓸 수 있다.

interface CraftBeer {
  brand?: string;
  [propName: string]: any;
}

 

함수 타입

함수의 타입을 정의할 때에도 인터페이스를 활용할 수 있음.

interface login {
  (username: string, password: string): boolean;
}

let loginUser: login;
loginUser = function(id: string, pw: string) {
  console.log('로그인 했습니다');
  return true;
}

 

클래스 타입

자바처럼 클래스가 일정 조건을 만족하도록 타입 규칙을 정할 수 있음.

interface CraftBeer {
  beerName: string;
  nameBeer(beer: string): void;
}

class myBeer implements CraftBeer {
  beerName: string = 'Baby Guinness';
  nameBeer(b: string) {
    this.beerName = b;
  }
  constructor() {}
}

 

인터페이스 간 확장

interface Person {
  name: string;
}
interface Developer extends Person {
  skill: string;
}
let fe = {} as Developer;
fe.name = 'josh';
fe.skill = 'TypeScript';

- 이렇게 인터페이스 간 상속도 되고, 아래처럼 여러 인터페이스를 상속받을 수도 있음.

interface Person {
  name: string;
}
interface Drinker {
  drink: string;
}
interface Developer extends Person, Drinker {
  skill: string;
}
let fe = {} as Developer;
fe.name = 'josh';
fe.skill = 'TypeScript';
fe.drink = 'Beer';

 

하이브리드 타입

함수 타입이면서 객체 타입도 정의하는 하이브리드 타입의 인터페이스 구성도 가능함

interface CraftBeer {
  (beer: string): string; // 함수처럼 호출할 수 있다는 의미. 
  brand: string;
  brew(): void;
}

function myBeer(): CraftBeer {
  let my = (function(beer: string) {}) as CraftBeer;
  my.brand = 'Beer Kitchen';
  my.brew = function() {};
  return my;
}

let brewedBeer = myBeer();
brewedBeer('My First Beer');
brewedBeer.brand = 'Pangyo Craft';
brewedBeer.brew();

'언어 > TypeScript' 카테고리의 다른 글

Union Type, Intersection Type  (0) 2025.04.14
enum 자료형  (0) 2025.04.13
함수  (0) 2025.04.11
기본 타입  (0) 2025.04.11
어째서 타입스크립트인가?  (0) 2025.04.11