본문 바로가기

Study/TypeScript

Interface

what is Interface? | vs. class, type 

ts에서 인터페이스란, 객체의 구조를 정의할 때 사용하는 키워드이다. 즉, 객체의 타입만을 정의하기 때문에, 같은 구조의 객체를 생성하는 클래스와는 차이가 있다. 

 

interface Person {
    // name: string = 'Harry'; => error! 
    // an interface cannot have an initializer;
    name: string;
    age: number; 
    greet(phrase: string): void; 
}

let harry: Person =  {
    name: 'Harry',
    age: 25,
    greet(phrase: string) {
        console.log(this.name + ' : ' + phrase)
    }
}
harry.greet('hi!');

/*
class Person {
    constructor(name: string) {
        this.name = name;
    }
}
*/

 

  1. 첫글자를 대문자로 작성하는 것이  컨벤션이다. 
  2. 프로퍼티의 초기값을 할당하는 것은 불가능하고, 그 타입만을 지정할 수 있다.
  3. 메서드의 경우에도 그 구조를 정의하는 것만 가능하다. 

 

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

 

 

위와 같이 정의하면, type Person을 interface Person과 동일하게 사용할 수 있다. 그렇다면 type과 interface의 차이점은 무엇일까? 

 

  1. interface는 객체의 구조를 정의할 때에만 사용할 수 있는 키워드이다. 반면 type은 유니언, 리터럴, 객체... 등 모든 사용자 타입을 지정할 때 사용할 수 있는 유연한 키워드이다. 따라서 interface를 사용하면, 객체의 구조를 정의하고 있다는 것을 보다 명백하게(clearer) 전달할 수 있다. 
  2. implements | 클래스를 정의할 때 interface를 이용할 수 있다. => 클래스가 그 interface에 정의된 객체의 구조를 따라야 한다는 것을 의미한다. 

 

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

interface Eatable {
  eat(food: string): void; 
}

// 여러 interface를 따르도록 할 수 있다
// interface에 정의된 속성/메서드를 클래스 내부에서 작성해 주어야 한다 
class Person implements Greetable, Eatable {
    constructor(public name: string, public age: number) {
    }
    greet(phrase: string): void {
        console.log(this.name + ':' + phrase)
    }
    eat(food: string): void {
        console.log(this.name + 'is eating' + food)
    }
}

 

  • 서로 같은 기능을 공유하는 다른 클래스를 만들 때 interface를 유용하게 사용할 수 있다.

readonly 

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

class Person implements Greetable {
    name: string;
    
    constructor(name) {
      this.name = name; 
    }
    greet(phrase: string): void {
        console.log(this.name + ':' + phrase)
    }
}

const me:Greetable = new Person('me');
me.name = 'new name'; // error!

 

  1. class에서 사용하는 public, private 같은 키워드는 사용할 수 없다. 
  2. readonly | 객체의 속성 앞에 readonly 제어자를 사용하면, 그 속성 값을 한 번 설정한 이후에는 값을 읽는 것만 가능하다. 
  3. 예제에서 me의 타입을 Greetable로 지정했기 때문에, name을 재할당 하려고 하면 에러가 발생한다. 

extends

인터페이스끼리도 클래스에서처럼, 상속을 구현할 수 있다. 

 

interface Named {
  readonly name: string; 
}

// 여러 개의 interface를 확장에 사용할 수 있다 
interface Greetable extends Named {
  greet(phrase: string): void;
}

// name 속성과 greet 메서드를 모두 가지고 있어야 한다
class Person implements Greetable {
  name: string; 
  constructor(name) {
    this.name = name; 
  }
  greet(phrase: string) {
    console.log(phrase); 
  }
}

 

  1. Greetable 인터페이스는 Named을 상속하므로, Named에서 정의한 속성도 가지고 있어야 한다. 
  2. Named와 Named를 상속하는 Greetable을 나누어 관리함으로써, name만 가지는 객체와 name, greet을 가지는 객체를 나누어 만들 수 있다. 

optional 

객체의 구조 안에 반드시 포함되어야 하는 속성/메서드가 아닌 경우에는 optional properties/methods로 지정할 수 있다. 

 

interface Named {
  readonly name: string; 
  nickName? : string;
  // 매개 변수를 option으로 만들 수도 있다 
  greet?(phrase?: string): void; 
}

function & interface 

type 키워드를 이용하면 함수의 구조 또한 정의할 수 있다. js에서 함수도 객체이기 때문에, interface를 이용해서 함수의 구조를 정의할 수 있다. 

 

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

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

let add:AddFn = (x: number, y:number) => {
  return x+y; 
}

 

  • 객체의 메서드를 정의할 때와는 달리 이름을 정하지 않고, 인자와 반환값의 타입만 정한다. 

compile

인터페이스에 관한 모든 것들은 자바스크립트로 컴파일 되면서 사라진다. ts가 개발 과정에서 제공하는 기능이라 자바스크립트에는 존재하지 않는 기능이기 때문이다. 

'Study > TypeScript' 카테고리의 다른 글

Generic  (0) 2022.07.24
Advanced Types  (0) 2022.07.23
Class  (0) 2022.07.21
tsconfig | ts compiler  (0) 2022.07.17
Types  (0) 2022.07.17