본문 바로가기
개발이야기/React

[React] TypeScript - type과 interface

by hyung12 2022. 4. 6.
반응형

TypeScript에서는 props 타입을 선언할 때 typeinterface를 사용한다

둘 다 타입을 선언한다는 공통점이 있지만 이 둘은 다르다


type

객체 타입 뿐 아니라 모든 타입에 대해 새로운 이름을 붙일 수 있다

// 예문

type TUser = {
  id: number;
  name: string;
};

const typeUser: TUser = {
    id: 0,
    name: '김하나',
};

interface

객체 타입을 만드는 또 다른 방법이다

// 예문

interface IUser = {
  id: number;
  name: string;
};

const interfaceUser: IUser = {
  id: 0,
  name: '김하나',
};

확장하기

// interface 확장하기

interface IUser {
  id: number
  name: string
}

interface IUser2 extends IUser {
  age: number
}


// type 확장하기

type TUser = {
  id: number
  name: string
}

type TUser2 = TUser & { 
  age: number
}

차이점(선언 병합)

typeinterfece는 매우 유사하기에 둘 중 하나를 선택하여 사용할 수 있지만 interface가 가지는 대부분의 기능은 type에서도 동일하게 사용 가능하다

이 둘의 차이점은 type은 새 속성을 추가하기 위해 동일한 이름으로 선언할 수 없는 반면, interface는 새 속성을 확장할 수 있다는 점이다

// interface 선언 병합

interface IUser {
  id: number
  name: string
}

interface IUser {
  age: number
}

const user1: IUser = {
  id: 0,
  name: '김하나',
  age: 20,
};


// type 선언 병합

type TUser = {
  id: number
  name: string
};

type TUser = {
  age: number
};

 // Error: Duplicate identifier 'TUser'.
 // type은 생성된 뒤에는 달라질 수 없다

 

type 이름이 오류 메세지는 경우에 따라 나타날 수도 있고 아닐 수도 있지만 interface는 항상 오류 메세지에 이름이 나타난다(참고)

// Compiler error messages will always use 
// the name of an interface:

interface Mammal {
    name: string
}

function echoMammal(m: Mammal) {
    console.log(m.name)
}

// e.g. The error below will always use the name Mammal 
// to refer to the type which is expected:
echoMammal({  name: 12343 })

// When a type hasn't gone through any form of manipulation
// then you still get the name as a reference:

type Lizard = {
    name: string
}

function echoLizard(l: Lizard) {
    console.log(l.name)
}

// So this still refers to Lizard
echoLizard({ name: 12345})

// But when a a type has been transformed, for example via this
// Omit then the error message will show the resulting type
// and not the name

type Arachnid = Omit<{ name: string, legs: 8 }, 'legs'> 

function echoSpider(l: Arachnid) {
    console.log(l.name)
}

echoSpider({ name: 12345, legs: 8})

 

type은 선언 병합에 포함될 수 없지만 interface는 선언 병합에 포함될 수 있다

// An interface can be re-opened
// and new values added:

interface Mammal {
    genus: string
}

interface Mammal {
    breed?: string
}

const animal: Mammal = {
    genus: "1234",
    // Fails because breed has to be a string
    breed: 1
}

type Reptile = {
    genus: string
}

// You cannot add new variables in the same way
type Reptile = {
    breed?: string
}

 

interface는 객체를 선언하는 데에만 사용된다

// Here's two examples of 
// using types and interfaces
// to describe an object 

interface AnObject1 {
    value: string
}

type AnObject2 = {
    value: string
}

// Using type we can create custom names
// for existing primitives:

type SanitizedString = string
type EvenNumber = number

// This isn't feasible with interfaces
interface X extends string {

}

 

interfeace는 항상 있는 그대로 오류 메세지에 나타난다

단, 해당 interface가 이름으로 사용되었을 때에만 해당한다

// Compiler error messages will always use 
// the name of an interface:

interface Mammal {
    name: string
}

function echoMammal(m: Mammal) {
    console.log(m.name)
}

// e.g. The error below will always use the name Mammal 
// to refer to the type which is expected:
echoMammal({ name: 12343 })

// The type of `m` here is the exact same as mammal,
// but as it's not been directly named, TypeScript
// won't mention it in the error messaging

function echoAnimal(m: { name: string }) {
    console.log(m.name)
}

echoAnimal({ name: 12345 })

대부분의 경우 개인적 선호에 따라 typeinterface 중에서 선택 사용할 수 있지만

공식문서에는 interfeace를 사용하고 이후 문제가 발생하였을 때 type을 사용하기를 권한다


출처
https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces

 

Documentation - Everyday Types

The language primitives.

www.typescriptlang.org

unsplash @ajny

반응형