[TypeScript] 여러 타입 선언 방법과 interface & type Alias 비교

skawnkk·2021년 10월 5일
4

자바스크립트

목록 보기
10/10

💙 상속받기

A+B=>A'
상속을 통해 중복되는 타입 nameage의 중복을 피할 수 있다.

interface Person{
  name: string;
  age?:number;
}
interface Developer{
  name: string;
  age?:number;
  skill : string[]
}

interface

상속받고자 하는 타입을 extends로 받아올 수 있다.

interface Developer extends Person{
  skill: string[]
}

type Alias

상속받고자 하는 타입을 선언하고 &연산자를 표기한 후 자신의 타입을 지정한다.

type Person = {
  name: string;
  age?: number;
  job?: string;
}
type Developer = Person & {
  skill : string[]
}
type barista = Person['job'] //string type

💙 Intersection 타입 사용하기

A+B=>C
이미 존재하는 타입 여러개를 하나의 타입으로 만들 때 사용된다.
상속으로 구현할 수도 있겠지만 상속받은 타입에서 상속된 타입을 필요로 하지 않는 경우에 타입에러의 가능성이 발생할수도 있기 때문에
자신의 타입은 고수하면서 새로운 병합된 타입을 만드는 것이다.
병합시킬 땐 A&B 형태로 선언하고, 이는 interface이든 type Alias든 동일하다.

interface Cafe{
    menu: string[]
}
interface Bank{
    money: number[]
}

const cafe:Cafe = {menu:['coffee', 'milk']}
const bank:Bank = {money:[100,200]}
const cafeManuel = (cafe:Cafe, bank:Bank): Cafe&Bank => ({...cafe, ...bank})

const newCafe = cafeManuel(cafe, bank)
console.log(newCafe)
/* {
  "menu": [
    "coffee",
    "milk"
  ],
  "money": [
    100,
    200
  ]
} 
*/

💙 Union 타입 사용하기

  • Union Type 은 자바스크립트의 OR(||)연산자와 같은 의미의 타입을 말한다. 이 타입을 선언할 때에는 데이터의 형태에 따라 유용한 타입 선언법이 달라지는데 변수 자체(원시형 데이터)에 타입을 지정할 것이라면 type Alias가 더 효과적이다.

type Alias

type Color = "red" | "purple" | "orange";
const color: Color = "orange";

color를 선언할 때 3가지 색 중에 한가지만 선택할 수 있도록 탭이 떠서 선택이 가능하다.

interface

반면, interface에서는 key값이 요구되기 때문에 객체 형태의 데이터 속성에 유니온타입을 줄 때 사용할 수 있다.

interface Color2 {
  color: "red" | "purple" | "orange";
}

const color2: Color2 = { color: "purple" };

💙 Index 타입 선언하기

index타입은 타입선언을 JavaScript처럼 좀 더 유연하게 줄 수 있는 타입이다. 이는 객체형 타입을 나타내므로 type Aliasinterface모두 작성법이 동일하다.

interface Props {
  name: string;
  age: string;
  [key: number]: string;
}
const testObject: Props = {
  1: "13",
  2: "23",
  3: "33",
  name: "namju",
  age: "50",
};

console.log(testObject.age);  //50
console.log(testObject["1"]); //13
console.log(testObject[1]);   //13

key에는 오로지 string 과 number 타입만 지정할 수 있다.✨
[key: number]: string; 는 number 타입의 키와 string 타입의 값을 갖는 타입을 의미하고, nameage라는 키를 필수로 가져야함을 나타낸다. 숫자와 name, age 외의 키 값을 선언하면 타입에러가 생긴다.

또한, 전체적인 인덱스 타입의 형태에 맞춰지는데 만일, age의 값으로 number로 주는 것은 불가능하다. number를 지정하고 싶다면
인덱스타입의 값이 string|number 타입으로 변경되어야 한다.

keyof

타입의 key값을 keyof로 접근할 수 있다.

let keyOfObjects: keyof Props;
keyOfObjects = "age";
console.log(testObject[keyOfObjects]);//50

keyOfObject에 올 수 있는 값은 1, 3, name, age 외 기타 숫자 타입의 key값이다. 기타 숫자 타입의 키가 올 수 있는 것은 인덱스 타입의 키를 number로 지정했기 때문이다.

type error case 1) age, name 외의 string 지정

let keyOfObjects: keyof Props;
keyOfObjects = "address"; 
//Type '"address"' is not assignable to type 'keyof Props'.

type error case 2) testObject에 존재하지 않는 key지정

let keyOfObjects : keyof Props;
keyOfObjects = 7 //-> 타입선언은 가능
console.log(testObject[keyOfObjects]) //undefined

💙 기존의 타입에서 특정 타입을 재 사용하기

기존의 타입들은 interface이든 Alias인지 상관없다.
기존 객체형 타입의 key로 접근하여 해당 type을 재사용 할 수 있다.

  • type Alias
    원시형 데이터에 새로운 타입을 선언할 때엔 type Alias가 사용된다.
interface Person {
  name: string;
  age?: number;
  job?: string;
}
interface Developer extends Person {
  skill : string[]
}
type Barista = Person['job'] //string type
const barista:Barista = 'coffee maker'
  • Interface
    interface를 사용할 수 있는 경우는 역시 객체형 데이터 일때이다.
interface Person {
  name: string;
  age?: number;
  job?: string;
}
interface Developer extends Person {
  skill : string[]
}
interface Barista {
    result: Person['job'] | Person['age'] //string or number
}
const barista:Barista = {result: 100}

💙 Declaration Merging

interface는 type을 중복하여 작성할 수 있고 확장성에 유리하다.✨

interface Test{
    score: number
}

interface Test{
    title: string
}

const prevTest:Test = {score: 500} // typeError
const mainTest:Test = {title: 'math', score:100}

type Alias는 중복하여 작성할 수 없다.

type Test = {
  score: number
}

type Test = {
  title: string
}
//Duplicate identifier 'Test'.

이러한 이유로 확장성이 요구되는 public API, 3rd party 라이브러리와 관련된 프로젝트에서는 interface를 사용하는 것이 좋다. 때문에 interface를 사용하면서 원시형 데이터에 union type을 지정하는 경우 등에 type Alias를 사용하도록 타입스크립트에서 권장한다고 한다.

하지만 일반적인 리액트 프로젝트에서 위와 같은 Declaration Merging을 사용할 일은 거의 없으므로 사용자의 기준에 따라 일관성을 갖고 쓰는 것이 좋다.


React에서의 타입선언

  • Object , Interface , type Alias 3가지를 모두 사용할 수 있다.
    • Object : type의 재 사용이 불가능 하므로 여러번 사용되는 타입은 interface나 Alias로 선언하는 것이 좋다.
//Object : 재사용 x
function SampleComponent(sample:{name: string, age:number}){
  ....
}
//Interface
Interface SampleProps{
  name: string
  age: number
}

fuction SampleComponent(sample: SampleProps){
  ...
}
  • 타입의 세부내용을 확인할 수 있는가?
    • type Alias : IDE에서 해당 타입에 마우스를 댔을 때, 내부 프로퍼티를 모두 확인할 수 있어 디버깅이 용이, 개발 생산성이 좋다.
    • interface : 타입 명만 볼 수 있다.
      예시처럼 재사용되어 이름에 해당되는 타입을 바로 확인할 수 있다면, 간단하게 이름만 표시하는 것도 좋다. 타입선언이 복잡한 경우 유용

참고하면 좋을 자료들
interface-vs-type-alias-in-typescript

profile
Dev FE 기록, 행동, 회고 유후~ 💜

0개의 댓글