ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Typescript] Interface 와 Type 차이를 정확히 알아보자
    front-end/Javascript&Typescript 2023. 5. 10. 13:38

     

    리액트와 타입스크립트로 작업을 하다보면 type , interface로 전달 받은 props 혹은 함수의 파라미터 타입을 정의 하곤 하는데요

    Interface 와 Type 이 어떻게 다른지 자세히 알아보겠습니다~!

    Interface

    interface Animal {
      name: string;
    }
    
    interface Bear extends Animal {
      honey: boolean;
    }
    
    const getBear = ({ name, honey }: Bear) => {
      return {
        name,
        honey
      };
    };
    
    const bearParams: Bear = {
      name: 'pubao',
      honey: true
    };
    
    const bear: Bear = getBear(bearParams);
    
    console.log(bear.honey);
    console.log(bear.name);

    TypeScript에서 같은 이름으로 선언된 인터페이스는 "인터페이스 병합(Interface Merging)"을 통해 하나의 인터페이스로 합쳐집니다. 이는 기존 인터페이스에 새로운 인터페이스의 내용을 확장하는 것과 유사하게 동작하지만, 정확히는 extend 키워드를 사용하는 것과는 차이가 있습니다.

    인터페이스 병합은 동일한 이름을 가진 인터페이스들이 모두 같은 루트 범위(같은 스코프 또는 동일한 파일)에 있을 때 발생합니다. 그리고 같은 이름으로 선언된 인터페이스들은 모두 하나로 합쳐지며, 프로퍼티와 메서드들은 모두 하나의 인터페이스에 포함됩니다. TypeScript는 인터페이스 병합을 통해 이들을 하나로 합쳐서 사용합니다. 따라서, 예시에서와 같이 WindowConfig라는 동일한 이름으로 두 개의 인터페이스가 선언된 경우에는 병합이 이루어져서 다음과 같은 결과가 됩니다

     

    이는 두 인터페이스가 합쳐져서 name과 title 속성을 모두 가져야하는 하나의 WindowConfig 인터페이스로 되었음을 의미합니다. 따라서 이후 코드에서 WindowConfig를 사용할 때 name과 title 속성을 모두 포함하는 객체를 사용해야 합니다. 이것은 일종의 확장(extend)처럼 보이지만, 실제로는 인터페이스 병합의 개념입니다. extend와는 목적과 동작이 조금 다르기 때문에 주의해야 합니다.

    interface WindowConfig {
      name:string;
    }
    
    interface WindowConfig {
      title:string;
    }
    
    
    function windowFn({title}:WindowConfig):string{
      return title;
    }
    
    const getWindowFn = windowFn({title:'제목',name:'이름'});
    
    //After merging
    interface WindowConfig {
      name: string;
      title: string;
    }

     

    Type

    type Window {
      title: string;
    }
    type Window {
      name: string;
    }
    
    function windowFn({title}:WindowConfig):string{
      return title;
    }
    
    const getWindowFn = windowFn({title:'제목',name:'이름'});
    
    // Error Duplicate identifier 'Window'.
    // 'Window' was also declared here.

    type은 애초에 같은 이름이면 에러를 발생 시킵니다.

     

    Type은 주로 복잡한 타입을 정의하는 데 사용됩니다. 객체뿐만 아니라, 유니온 타입, 튜플, 리터럴 타입 등 다양한 타입을 정의하는 데 사용할 수 있습니다. Type은 기존 타입이나 인터페이스를 조합하여 새로운 타입을 만들 수 있습니다.

     

    type Point = {
      x: number;
      y: number;
    };
    
    type ShapeType = "circle" | "square" | "triangle";
    
    const point: Point = {
      x: 10,
      y: 20,
    };
    
    function getShapeType(shape: ShapeType) {
      // ...
    }

    keyof 연산자

    type Person = { name: string; age: number };
    type PersonType = keyof Person; // name | age

    typeof 타입 연산자 
    typeof는 변수 또는 속성의 타입을 참조하는 데에 타입 컨텍스트에서 사용될 수 있습니다.

    예시1

    let name = 'John';
    let NType: typeof name; // NType는 string 타입입니다.

    에시2

    let person = {
      code: "1",
      name: "Rahul",
    };
    let employee: typeof person;
    employee = { code: "2", name: "Sachin" }; // 성공
    employee = { code: "2", name: "Sachin", salary: 1000 }; // 오류 - '{ code: string; name: string; salary: number; }' 타입은 '{ code: string; name: string; }' 타입에 할당할 수 없습니다.


    매핑된 타입 다른 타입을 기반으로 새로운 타입을 만드는 데에 사용될 수 있습니다.

     

    type OptionalFlags<T> = {
      [Property in keyof T]: boolean;
    };
    
    type FeatureFlags = {
      darkMode: () => void;
      profile: () => void;
    };
    
    type FeatureOptions = OptionalFlags<FeatureFlags>;
    // { darkMode: boolean, profile: boolean }


    매핑 수정자 매핑 중에 적용할 수 있는 두 가지 추가적인 수정자는 읽기 전용 (readonly)과 선택적인 (?)입니다. 

    이러한 수정자를 추가하거나 제거하기 위해 - 또는 +로 접두사를 붙일 수 있습니다. 접두사를 붙이지 않으면 +가 기본으로 가정됩니다.

    // 타입의 속성에서 'readonly' 속성을 제거합니다.
    type CreateMutable<T> = {
      -readonly [Property in keyof T]: T[Property];
    };
    
    type LockedAccount = {
      readonly id: string;
      readonly name: string;
    };
    
    type UnlockedAccount = CreateMutable<LockedAccount>;
    // { id: string; name: string }
    // readonly가 제거된 것을 볼 수 있습니다.




    요약 

    Interface: 주로 객체의 구조를 정의하는 데 사용됩니다. 객체의 속성과 메서드를 선언하는 데에 사용됩니다. 여러 객체가 공통적인 구조를 공유하도록 하거나, 클래스를 구현하는 데에 사용됩니다. 확장이 가능하므로, 기존 Interface를 확장하여 새로운 인터페이스를 생성할 수 있습니다.

    Type: 주로 복잡한 타입을 정의하는 데 사용됩니다. 객체뿐만 아니라, 유니온 타입, 튜플, 리터럴 타입 등 다양한 타입을 정의하는 데에 사용됩니다. 기존 타입이나 인터페이스를 조합하여 새로운 타입을 만들 수 있습니다.새로운 타입을 만들 때는 기존 Type을 수정하거나 조합하여 사용해야 합니다.



    Reference
    https://javascript.plainenglish.io/typescript-essentials-you-should-know-d026f9e88bc1

     

    TypeScript Essentials You Should Know

    Learn these basics to make better use of TypeScript.

    javascript.plainenglish.io

     

Designed by Tistory.