[TS] interface(인터페이스)와 index signature(인덱스 서명)

정(JJeong)·2023년 1월 30일
0

TypeScript 익히기

목록 보기
3/10
post-thumbnail

typescript에서 사용 가능한 interface기능을 공부하고 어떻게 활용하는지 알아보자.

오류 상황

let use:object;

user = {
  name: 'Tom',
  age: 30
};

console.log(user.name);

위 코드를 실행해보면 user.name의 name쪽에 에러가 발생한다. 그 이유는 user가 object인 것은 알지만 그 안의 property(프로퍼티)값의 타입은 지정되지 않아 모르기 때문이다.

이럴 때 property를 정의해서 사용하고자 한다면 interface를 이용하면 된다.


📌 객체에서 interface

작성법

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

위와 같은 방식으로 User라는 객체 형태의 타입을 만들어줄 수 있고, 이 안에는 해당 객체가 가질 수 있는 프로퍼티와 그에 대한 타입이 지정되어 있다.

이는 아래와 같이 사용된다.

사용해보기

let user1:User = {};	// Error

let user2:User = {
  name: 'Tom',
  age: 30
}

위 코드에서 user1은 User가 타입으로 지정되었고 객체이지만 에러가 뜬다. 그 이유는 name과 age 프로퍼티를 지니지 않았기 때문이다.



📌 추가적인 설정

옵션 지정

아래 코드를 작성해보면 let user에 밑줄이 가며 에러가 뜬다. 이유는 interface에서 User는 gender라는 프로퍼티까지 지닌다고 설정해두었는데 let user에는 gender 프로퍼티가 작성되지 않았기 때문이다.

// 옵션 미지정시
interface User {
  name: string;
  age: number;
  gender: string;
}

let user:User = {
  name: 'Tom',
  age: 30
}

그렇다면 만약 어떠한 프로퍼티값은 지닐 수도 있고 아닐 수도 있게 지정하고 싶다면 어떻게 해야할까? 아래와 같이 ?만 붙여주면 된다.

interface User {
  name: string;
  age: number;
  gender?: string;	// 옵션으로 지정
}

let user:User = {
  name: 'Tom',
  age: 30
}


read only 설정

이번엔 읽어오는 것만 가능하고 수정은 불가한 read only를 만들어보자.
아주 간단히 앞에 readonly만 붙여주면 된다.

interface User {
  name: string;
  age: number;
  gender?: string;
  readonly birthYear: number;	// 읽어오기 전용
}

let user:User = {
  name: 'Tom',
  age: 30,
  birthYear: 1999
}

user.birthYear = 2002;	// 수정불가이기 때문에 에러

이러면 생성시에만 부여가 가능하고 이후 수정은 불가하다.


📌 인덱스 서명


Question

1. 만약 객체의 {key: value}가 갖는 값은 다르지만 type은 동일한 프로퍼티를 여러개 지닐 수 있도록 하고 싶다면?
ex) {a: 2, b: 5} -> 각각이 {string: number}로 같은 유형을 지님

2. 이러한 key들의 타입은 알되 정확히 어떤 내용이 작성될지 모를 때엔?
ex) key는 number, value는 string이 확실한데, key에 뭐가 들어가지? 1? 2?

3. 그리고 프로퍼티는 optional하게 하여 각 interface로 만들어진 객체마다 다르게 작성하고 싶다면?


이 때 사용하는 것이 인덱스 서명이다.

interface User {
  name: string;
  age: number;
  gender?: string;
  readonly birthYear: number;
  [grade: number]: string;
}

이렇게 하면 위에서 확인할 수 있듯이 key를 number로 가지고, value를 string을 가지는 프로퍼티를 여러개 가질 수도 있고, optional하기 때문에 작성하지 않을 수도 있다.

참고: grade라는 건 사용자정의이므로 아무렇게 작성 가능하다.

['example': number]: string;


📌 함수에서의 interface

이러한 interface는 객체 뿐 아니라 함수에서 인수를 지정하는 데에도 사용할 수 있다.

예시1

interface Add {
  (num1: number, num2:number): number;
}

이때 (num1: number, num2:number): 뒤에 작성된 number는 return값에 대한 지정으로, 만약 return이 없다면 void로 지정해주면 된다.

그리고 이때 작성한 num1, num2라는 인수의 이름은 사용자정의로 사용할 수 있다.

const add: Add =function(x,y) {
  return x+y;
};

add(10,20);		// Run
add(10,'20');	// Error

예시2

interface IsAdult {
  (age:number): boolean;
}

const verifying: IsAdilt = (age) => {
  retunr age > 19;
}

verifying(30);	// true
verifying(15);	// false


📌 interface로 Class정의하기

interface를 이용해 Class를 정의하는 것도 가능하다. 아래에 작성된 Car라는 interface를 통해 알아보자

사용할 interface 코드

interface Car {
  color: string;
  wheels: number;
  start(): void;
}

잘못된 사용

class Bmw implements Car {
  a = 3;
}

이렇게만 작성하면 오류가 뜬다. 사진처럼 오류가 뜨고, interface Car에 맞는 값이 없다고 한다. 그렇다면 이에 맞는 속성값들을 넣어주자.

올바른 작성법

class Bmw implements Car {
  color: 'red';
  wheels: 4;
  start() {
    console.log('go!');
  };
}

오류없이 잘 작동한다. 이제 여기에 Class답게 constructor도 넣어주도록하자. 이때 color에 대한 값은 받아오게 만들자.

class Bmw implements Car {
  color;
  constructor (c:string) {
    this.color = c;
  }
  wheels = 4;
  start() {
    console.log('go!');
  }
};

const b = new Bmw('green');

위 코드를 작성하면 컴파일 과정을 거쳐 아래와 같은 JS 코드가 된다.



📌 inferface 확장

또한 interface를 extends를 이용해 확장해서 사용하는 것도 가능하다. 위의 예시 코드를 이용해 만들어보면,

interface Car {
  color: string;
  wheels: number;
  start(): void;
}

interface Audi extends Car {
  sheet: number;
  stop(): void;
}

이같이 Car라는 interface를 확장해서 sheet와 stop()이라는 속성을 지닌 새로운 Audi라는 interface를 만들었다.

Audi는 Car를 확장한 것이기 때문에 Car의 속성도 모두 지니게 작성되어야 한다.

여러개를 한번에 포함하여 확장하기

extends는 여러개를 한번에 하는 것도 가능하다.

interface Car {
  color: string;
  wheels: number;
  start(): void;
}

interface Engine {
  horsepower: number;
}

interface Supercar extends Car, Engine {
  sheet: number;
  stop(): void;
}

이렇게 하면 Supercar라는 interface는 Car와 Engine 모두의 속성을 지니며 sheet와 stop()이라는 속성도 가지게 된다.




P.S. interface를 공부하다보니 계속 추가적으로 꼬리물기처럼 더 궁금한 것, 알아야할 것들이 생긴다.

호기심 넘치는데 동시에 머리 터지겠다..🤯




profile
2년차 응애 FE 개발자입니다👶

0개의 댓글