업 캐스팅, 다운 캐스팅

정민교·2023년 10월 6일
0

typescript

목록 보기
3/17

📒업 캐스팅, 다운 캐스팅

부모 타입(상위 타입)의 변수에 자식 타입(하위 타입)의 값을 할당하는 것을 업 캐스팅

반대의 경우를 다운 캐스팅이라고 합니다.

✔️unknown

unknown 타입은 타입 계층도에서 최상단에 위치한 타입입니다.

따라서 모든 타입은 unknown 타입으로 업 캐스팅이 가능합니다.

let a: unknown = 1;                 // number -> unknown
let b: unknown = "hello";           // string -> unknown
let c: unknown = true;              // boolean -> unknown
let d: unknown = null;              // null -> unknown
let e: unknown = undefined;         // undefined -> unknown
let f: unknown = [];                // Array -> unknown
let g: unknown = {};                // Object -> unknown
let h: unknown = () => {};          // Function -> unknown

하지만 반대로 unknown 타입은 다른 타입으로 다운 캐스팅이 불가능합니다.(any 타입 제외)

✔️never

never 타입은 타입 계층도의 최하위에 위치한 타입입니다.

let neverVar: never;

let a: number = neverVar;            // never -> number
let b: string = neverVar;            // never -> string
let c: boolean = neverVar;           // never -> boolean
let d: null = neverVar;              // never -> null
let e: undefined = neverVar;         // never -> undefined
let f: [] = neverVar;                // never -> Array
let g: {} = neverVar;                // never -> Object

따라서 never 타입은 모든 타입으로 업 캐스팅이 가능합니다.

반대로 어떤 타입도 never 타입으로 다운 캐스팅이 불가능합니다.

✔️void

void 타입은 아무것도 반환하비 않는 함수의 반환값 타입으로 주로 사용되며 unknown 타입의 상위 타입입니다.

function noReturnFunc(): void {
  console.log("hi");
}

따라서 void 타입을 반환값 타입으로 지정한 함수에서 undefined 값을 반환하여도 가능합니다.

업 캐스팅이 가능하기 때문입니다.

void 타입의 하위 타입은 undefinednever 타입만 존재하기 때문에 void 타입 변수에는 undefined, never 타입의 값 외의 다른 타입의 값은 할당할 수 없습니다.

let voidVar: void;

voidVar = undefined; // undefined -> void (ok)

let neverVar: never;
voidVar = neverVar; // never -> void (ok)

✔️any

any 타입은 치트키 타입입니다.

모든 타입으로 업 캐스팅이 가능하고 모든 타입으로 다운 캐스팅도 가능합니다.

✔️객체 타입

type Animal = {
  name: string;
  color: string;
};

type Dog = {
  name: string;
  color: string;
  breed: string;
};

let animal: Animal = {
  name: "기린",
  color: "yellow",
};

let dog: Dog = {
  name: "돌돌이",
  color: "brown",
  breed: "진도",
};

animal = dog; // ✅ OK
dog = animal; // ❌ NO

타입스크립트는 프로퍼티를 기준으로 타입을 정의하는 구조적 타입 시스템을 따릅니다.

따라서 프로퍼티 갯수가 더 많은 Dog 타입이 상위 타입이라고 생각할 수 있지만 그 반대입니다.

쉽게 생각하면 Animal 타입은 name, color 프로퍼티를 가지고 있는 모든 객체의 집합입니다.

Dog 타입은 name, color, breed 프로퍼티를 가지고 있는 모든 객체의 집합입니다.

따라서 Dog 타입에 속하는 객체라면 당연히 Animal 타입에도 속하게 됩니다. 하지만 그 반대는 성립하지 않습니다.

따라서 Animal 타입은 Dog 타입의 상위 타입이라고 말할 수 있습니다.

그러므로 Dog 타입은 Animal 타입으로 업 캐스팅이 가능하지만, Animal 타입은 Dog 타입으로 다운 캐스팅이 불가능합니다.

📌초과 프로퍼티 검사

type Book = {
  name: string;
  price: number;
};

type ProgrammingBook = {
  name: string;
  price: number;
  skill: string;
};

(...)

let book2: Book = { // 오류 발생
  name: "한 입 크기로 잘라먹는 리액트",
  price: 33000,
  skill: "reactjs",
};

Book 타입과 ProgrammingBook 타입을 타입 별칭으로 정의했습니다.

그리고 Book 타입 변수를 선언하고 객체를 할당하였습니다. name, price, skill 프로퍼티를 갖는 객체는 Book 타입의 하위타입이기 때문에 업 캐스팅이 가능해야 합니다.

하지만 위와 같은 경우에 오류가 발생합니다.

이유는 초과 프로퍼티 검사 때문입니다.

초과 프로퍼티 검사는 변수를 객체 리터럴로 초기화 할 때 발동합니다.

Book 타입은 name, price를 프로퍼티로 갖는 객체 타입인데, skill 프로퍼티를 갖는 객체 리터럴을 Book 타입 변수에 할당하려고 했기 때문에 초과 프로퍼티 검사가 발동합니다.

초과 프로퍼티 검사는 객체 리터럴을 할당하는 경우에만 발동되기 때문에 값을 미리 다른 변수에 보관하고 이 변수를 할당하면 가능합니다.

초과 프로퍼티 검사는 함수의 매개변수에도 동일하게 작동합니다.

function func(book: Book) {}

func({ // 오류 발생
  name: "한 입 크기로 잘라먹는 리액트",
  price: 33000,
  skill: "reactjs",
});

해결 방법도 동일하게 다른 변수에 할당한 후 변수를 인수로 넘겨주면 됩니다.

profile
백엔드 개발자

0개의 댓글