[인프런 타입스크립트 입문 - 기초부터 실전까지] - 인터페이스와 타입 별칭

Lee Jeong Min·2021년 12월 11일
0

TypeScript

목록 보기
4/18
post-thumbnail

이 글은 타입스크립트 입문 - 기초부터 실전까지의 인터페이스와 타입 별칭을 보고 정리한 글입니다.

앞서 첫 번째 프로젝트 - 할 일 관리 애플리케이션을 진행하면서 interface에 대한 개념을 보았다.

타입 별칭 버전

type Todo = {
  id: number,
  title: string,
  done: boolean
}

인터페이스 버전

interface Todo {
  id: number;
  title: string;
  done: boolean;
}

다음과 같이 정의하고, 인터페이스가 없다면 {id: number; title: string; done: boolean} 과 같이 길고 중복되는 것을 타입으로 적어주어야 한다. 이를 간단하게 하기 위해 위와 같은 Todo라는 인터페이스를 사용한다.

인터페이스 소개 및 변수를 정의하는 인터페이스

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

let jeongmin: User = {
  age: 25,
  name: '정민',
};

인터페이스 형식은 위와 같다. User라는 인터페이스가 정의되어 있다면 상호간의 약속했던 규칙에 따라 User 형식대로 작성해주어야 한다.

함수의 인자를 정의하는 인터페이스

// 함수에 인터페이스 활용
const getUser = (user: User) => {
  console.log(user);
};
const capt = {
  name: '캡틴',
};
getUser(capt)

함수에 아까 정의 해둔 User라는 인터페이스를 다음과 같이 사용하면 에러가 발생한다.

이 에러는 getUser함수 호출 시 전달되는 capt라는 인수가 User 인터페이스 형식에 맞지 않아서 발생하는 에러로 age 키와 값을 설정해주어야 한다.

// 함수에 인터페이스 활용
const getUser = (user: User) => {
  console.log(user);
};
const capt = {
  name: '캡틴',
  age: 100,
};
getUser(capt);

이러한 구조가 타입스크립트에서 가장많이 볼 수 있는 인터페이스 활용 구조이다.

함수 구조를 정의하는 인터페이스

인터페이스를 다음과 같이 함수 구조를 정의하는 방식으로 사용할 수 있다.

// 함수의 스펙(구조)에 인터페이스를 활용
interface SumFunction {
  (a: number, b: number): number;
}

let sum: SumFunction;
sum = function (c: number, d: number) {
  return c + d;
};

이와 같이 사용하게 되면 sum이라는 변수에는 funcntion을 할당할 때, 인수 두개가 number타입이어야 하며, 반환값도 number타입이어야 한다. 만약 아무것도 반환하지 않는 함수를 sum에 할당 시, 다음과 같은 에러를 볼 수 있다.

인덱싱 방식을 정의하는 인터페이스

// 인덱싱
interface StringArray {
  [index: number]: string;
}

let arr: StringArray = ['a', 'b', 'c'];
// 에러 발생 코드
arr[0] = 10; // 'a'

배열의 인덱싱 방식또한 인터페이스로 정의할 수 있다.
위 코드는 에러가 발생하는데, arr이라는 배열에 0번 인덱스로 접근하여 10을 할당하려고 하기 때문에 string타입을 인덱싱 방식으로 인터페이스로 정의해 두어 에러가 발생한다.

인터페이스 딕셔너리 패턴

// 딕셔너리 패턴
interface StringRegexpDictionary {
  [key: string]: RegExp;
}

let obj: StringRegexpDictionary = {
  sth: /abc/,
  cssFile: /\.css$/,
  jssFile: /\.js$/,
};

// obj['cssFile'] = 'a' // 에러 감지

Object.keys(obj).forEach(value => {});

딕셔너리 패턴으로 다음과 같이 사용할 수 있다. 또한 이렇게 작성하게 되면 Object.keys(obj).forEach(value => {}); 이 부분에서 value의 타입이 string 속성이라는 것을 타입추론에 의해 알려주는 것을 볼 수 있다.

인터페이스 확장(상속)

// 인터페이스 확장
interface Person {
  name: string;
  age: number;
}

interface Developer extends Person {
  language: string;
}

let captain: Developer = {
  language: 'ts',
  age: 100,
  name: '캡틴',
};

OOP처럼 확장하여 인터페이스를 사용할 수 있다.
Developer라는 인터페이스에 Person을 확장하게 되면 name, age, language를 모두 작성해야 에러가 발생하지 않는다.

타입 별칭 소개

타입 별칭은 특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미한다.

참고: https://joshua1988.github.io/ts/guide/type-alias.html#%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD-type-aliases

// number 타입 사용 시
const num: number = 123;

// 타입 별칭 사용 시
type MyNum = number;
const num2: MyNum = 123;

타입 별칭 코드 예제

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

type Person2 = {
  name: string;
  age: number;
};

let jm: Person = {
  name: '정민',
  age: 25,
};

let jm2: Person2 = {
  name: '정민',
  age: 25,
};

다음과 같은 코드가 있다고 하였을 시, jm: 옆의 인터페이스, 타입에 마우스를 갖다 대보면 아래의 결과를 확인할 수 있다.

인터페이스의 경우 그 안의 정보까지 보여주지는 않지만 타입의 경우 그 타입의 정보가 무엇인지 구체적으로 보여준다.

타입 별칭과 인터페이스의 차이점

타입은 확장 불가능, 인터페이스는 확장 가능

--> 가능한 한 interface 사용하는 것이 확장가능성 측면에서 더 좋다!

참고: https://joshua1988.github.io/ts/guide/type-alias.html#type-vs-interface

profile
It is possible for ordinary people to choose to be extraordinary.

0개의 댓글