front-end/TypeScript

[TypeScript] Interface

Ash_O 2023. 8. 7. 17:20

 

인터페이스 : 객체의 구조를 설명하는데 사용하는 사용자 정의 타입

interface Person {
  name: string;
  age: number;
  greet(phrase: string): void;
}

let user1: Person;

user1 = {
  name: 'Max',
  age: 30,
  
  greet(phrase: string) {
    console.log(phrase + this.name);
  }
};

 

사용자 정의 타입을 써도 똑같을텐데 왜 인터페이스를 쓸까?

 

인터페이스와 사용자 정의 타입은 완전히 같지는 않다.

 

인터페이스는 객체의 구조를 설명하기 위해서만 사용한다.

인터페이스를 정의하는 것은 객체라는 것을 명시하는 행위다.

또한, 클래스가 인터페이스를 준수해야하는 약속처럼 사용할 수 있다.

 

클래스 이름 뒤에 implements 키워드와 함께 준수할 인터페이스들을 작성하면 된다.

 

interface Greetable {
  name : string;
  greet(phrase: string): void;
}

class PersonClass implements Greetable {
  age = 30;
  constructor(public name:string){}

  greet(phrase: string): void {
    console.log(phrase + this.name)
  }
}

 

추상클래스와도 비슷해보일 수 있는데,

인터페이스는 구현 세부 사항이 없는 반면 추상클래스는 오버라이드 해야하는 부분, 구체적인 구현 부분을 혼합한다.

 

Readonly Interface Property

인터페이스 내부에는 읽기전용 키워드도 추가할 수 있다.

public이나 private는 안되지만 readonly는 가능하다.

프로퍼티가 최초 한번만 초기화되고, 그 이후에는 읽기 전용으로 설정해서 객체가 만들어지면 변경할 수 없도록 하게 한다.

이건 type 키워드에도 쓸 수 있다.

interface Greetable {
  readonly name: string;

  greet(phrase: string): void;
}

클래스에 Greetable을 전달하면, 클래스에서는 Greetable을 구현하겠다고 인지하고 name 필드가 readonly임을 자동으로 추론한다.

 

extends

인터페이스끼리는 상속이 가능하다.

 

왜 상속기능이 필요할까?

 

위에서 구현된 interface를 나누어 Person을 작성한다고 해보자

interface Named {
    readonly name: string;
}

interface Greetable {
    greet(phrase: string): void;
}

class PersonClass implements Greetable, Named {
    name: string
    age = 30;
    constructor(n:string){
        this.name = n;
    }

    greet(phrase: string): void {
        console.log(phrase + this.name)
    }
}

 

개발을 하다보면, 객체마다 필요로 하는 속성이나 메서드 조합이 다양할 수 있기 때문에

인터페이스가 분리되어 관리되는게 개발에 용이할 수 있다.

 

위와 같이 분리하고 여러 인터페이스를 클래스에 넘길수도 있는데, 상속을 활용해서 조합된 인터페이스를 새로 만드는 것도 유용하다.

interface Named {
  readonly name: string;
}

interface ExtendNamed extends Named {
  greet(phrase: string): void;
}

class Person implements ExtendNamed {
    name: string
    age = 30;
    constructor(n:string){
        this.name = n;
    }

    greet(phrase: string): void {
        console.log(phrase + this.name)
    }
}

 

지금은 클래스에서의 예시이지만,
상속을 활용하면 중복될만한 속성은 상속시키고 필요한 부분만 구현하면서 인터페이스를 효율적으로 만들어서 사용할 수 있다.

 

Function Interface

인터페이스는 객체의 구조를 설명한다.

 

함수타입은 사용자 정의 타입으로 정의할 수 있다.

 

인터페이스를 활용하여 함수 타입을 만들 수 있는데, 함수는 일급객체니까 인터페이스로 만들 수 있는 것이다

 

type AddFn = (a: number, b: number) => number;

interface InterfaceAddFn {
  (a: number, b: number): number;
}

 

일반적인 상황에서는 함수타입은 type을 사용해서 만드는게 좋다고 한다.


reference : 유데미 타입스크립트 강의

https://www.udemy.com/course/best-typescript-21/