[TS] 타입 앨리어스(Type Alias)와 인터페이스 상속

김채운·2023년 2월 21일
0

Typescript

목록 보기
4/7

➡️ Type Alias (타입 별칭)

특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미한다. 여러 프로퍼티를 갖는 객체 타입 같은 복잡한 경우에 사용하며, 타입을 재사용하고 이름을 지정하는 방법이다.

Type Alias 사용법

// string 타입을 사용할 때
const name: string = 'capt';

// 타입 별칭을 사용할 때
type MyName = string;
const name: MyName = 'capt';

type 키워드를 사용하여 타입에 이름을 설정하는 방법이다. 타입 별칭을 정의하는 방법은 type 뒤에 별칭을 입력하고 = 연산자 뒤에 타입을 정의한다.

union(|) 사용

타입 별칭을 union type으로 합치는 것도 가능하다.

type Name = string;
type Age = number;

type person = Name | Age;

intersection(&) 사용해서 확장(상속)하는 방법.

type Animal = {breath: true};
type mammalia = Animal & {breed: true};
type Human = mammalia & {think: true};

const me: Human = {breath: true, breed:true, think: true}

위에 코드는 예를 든건데 사람은 숨을 쉬는데 숨만 쉬면 안 되고, 포유류기 때문에 breed도 해야되고, 사람이기 때문에 think도 해야된다.
이런식으로 확장의 개념으로 쓸 수도 있다.(상속의 개념으로) 그래서&(intersection)을 그리고 라는 개념으로 생각하기 보다는, 상속의 개념으로 받아드려야 한다.

함수에 타입 별칭 사용.

함수에도 타입 별칭을 사용할 수 있다. 다음 코드는 string 타입인 name과 number 타입인 age를 매개변수로 받고 return 값의 타입이 string인 함수이다.

const stringFunc = (name: string, age: number): string => {
  return `name: ${name} / age: ${age}`;
}

// 별칭 생성
type stringFunc = {name: string, age: number} => string;

// 함수에 타입 별칭 사용.
const stringFunc: stringFunc = (name,age) => {
  return `name: ${name} / age: `${age}`;
}

➡️ 인터페이스의 상속(extends)

인터페이스 사용법


// 인터페이스
interface Person {
  name: string,
  age: number
}
// 빈 객체를 Person 타입으로 지정
let person:Person; // 커서 올리면 interface Person 타입이라고 추론 됨.

// 타입 앨리어스
type Person = {
  name: string,
  age: number
}
// 빈 객체를 Person 타입으로 지정
let person:Person; // 커서 올리면 type Person{name:string; age:number;} 타입으로 추론 됨.

person 변수를 const를 사용하였더니 'const' declarations must be initialized.라는 에러가 뜸. const' 선언은 반드시 초기화되어야 한다.라는 뜻인데, const 규칙을 어겨서 생긴 에러다. const 키워드는 반드시 선언과 초기화, 그리고 할당이 동시에 이루어져야 하는데 이론을 알고 있어도 실제 코드에서는 익숙하게 const를 쓰다 보니 생각하고 쓰지 않아서 이런 에러가 뜨게 됐다ㅠㅠ.

인터페이스의 상속 사용법

타입 앨리어스에서는 &로 상속(확장)을 시켰지만, interface에는 extends가 있다.

interface A {
    breath: true
}
interface B extends A {
    breed: true 
}

const b:B = {breath: true, breed: true}

이런식으로 위에 &와 비슷하게 사용할 수 있다.

❗또 다른 interface 특징중에 interface를 같은 이름으로 여러 번 선언할 수 있는 특징도 있다.

interface A {
    talk: () => void;
}
interface A {
    eat: () => void;
}
interface A {
   shit: () => void;
}

const a: A = {talk() {}, eat() {}, shit() {}}

type에서는 안 되는 것으로 interface는 이렇게 여러 번 선언할 수 있는데 선언할 때마다 합쳐진다.
그래서 라이브러리들이 대부분 다 타입이 아니라 interface로 만들어놨다. 왜냐? 우리들이 나중에 다른 사람들의 interface를 확장할 수도 있으니까 남의 라이브러리에 위에처럼 저런식으로 되어있다. 그런데 수정을 하고 싶거나 무언가를 더 추가하고 싶으면 👇

// 얘 따로 하나 추가해주면
interface A {
   sleep: () => void;
}
// 실제로 여기에 하나가 추가가 된다.
const a: A = {talk() {}, eat() {}, shit() {}, sleep() {}}

그래서 interface는 서로간에 합쳐진다는 특이한 습성이 있기 때문에 이 특성을 기반으로 남의 라이브러리 코드를 수정할 수 있는 것이다.

결론

type과 interface는 구조와 사용법이 매우 유사하다 둘 중에 뭘 쓰냐 고민하자면,
type은 typescript를 잘 모르는 사림이 보면 명확하지 못 하다. & 이게 뭘 뜻하는지 근데 interface를 쓰고 interface의 extends를 쓰면 extends자체로 확장의 의미 딱 명확하기 때문에 객체지향인 interface를 쓰는 걸 지향하는 것 같다. 또 다른 이유로는 인터페이스는 같은 이름으로 여러 번 선언할 수 있는 특징이 있기 때문에 확장에 용이하기도 하다.
따라서, 상속을 통해 확장이 필요하다면 타입 앨리어스보다는 인터페이스가 유리하다. 하지만 인터페이스로 표현할 수 없거나 유니온 또는 튜플을 사용해야한다면 타입 앨리어스를 사용하는 편이 유리하다.

출처

0개의 댓글