๋ฐ˜์‘ํ˜•

ํƒ€์ž… ํ˜ธํ™˜ Type Compatibility


๐Ÿ’ก ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์ด๋‚˜ ์ต๋ช… ํ•จ์ˆ˜ ๋“ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ช…์‹œ์ ์œผ๋กœ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ฝ”๋“œ์˜ ๊ตฌ์กฐ ๊ด€์ ์—์„œ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š”๊ฒŒ ๋” ์ž˜ ์–ด์šธ๋ฆด ์ˆ˜๋„ ์žˆ๋‹ค.

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ๋‹ค๋ฅธ ํƒ€์ž… ๊ฐ„์— ํ˜ธํ™˜ ์—ฌ๋ถ€๋ฅผ ์ ๊ฒ€ํ•˜๋Š” ๊ฒƒ์„ ํƒ€์ž… ํ˜ธํ™˜์ด๋ผ๊ณ  ํ•œ๋‹ค. ์•„๋ž˜ Avengers ํด๋ž˜์Šค๋Š” Ironman ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•œ ๊ฒŒ ์•„๋‹Œ๋ฐ๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  ํƒ€์ž…์— ์ •์˜๋˜์–ด ์žˆ๋Š” ์†์„ฑ์˜ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ์ฝ”๋“œ๊ฐ€ ํ˜ธํ™˜๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

interface Ironman {
  name: string;
}

class Avengers {
  name: string;
}

let ironMan: Ironman;
ironMan = new Avengers(); // ok ํƒ€์ž… ํ˜ธํ™˜

 

๊ตฌ์กฐ์  ํƒ€์ดํ•‘ Structural typing


๐Ÿ’ก ๊ฐ์ฒด ์†์„ฑ, ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ์ด ๋น„๊ตํ•˜๋Š” ๋Œ€์ƒ๋ณด๋‹ค ๋” ๋งŽ๋‹ค๋ฉด ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ํฌ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

์ฝ”๋“œ ๊ตฌ์กฐ ๊ด€์ ์—์„œ ํƒ€์ž…์ด ์„œ๋กœ ํ˜ธํ™˜๋˜๋Š”์ง€ ํŒ๋‹จํ•˜๋Š” ๊ฒƒ์„ ๊ตฌ์กฐ์  ํƒ€์ดํ•‘์ด๋ผ๊ณ  ํ•œ๋‹ค. ์•„๋ž˜ ์˜ˆ์ œ์—์„œ capt ๊ฐ์ฒด์™€ Avengers ์ธํ„ฐํŽ˜์ด์Šค ๋ชจ๋‘ name ์†์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— capt์™€ hero ํƒ€์ž…์€ ์„œ๋กœ ํ˜ธํ™˜๋œ๋‹ค. ๋” ์—„๋ฐ€ํ•˜๊ฒŒ ๋งํ•˜๋ฉด capt ๊ฐ์ฒด ํƒ€์ž…์ด ๊ตฌ์กฐ์ ์œผ๋กœ Avengers ๋ณด๋‹ค ํฌ๊ธฐ ๋•Œ๋ฌธ์— hero์— ํ• ๋‹น(ํ˜ธํ™˜)๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ.

interface Avengers {
  name: string;
}

let hero: Avengers;

const capt = { name: "Captain", location: "Seoul" };
hero = capt; // ok ํƒ€์ž… ํ˜ธํ™˜

 

ํ•จ์ˆ˜ ํ˜ธ์ถœ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค. capt ๊ฐ์ฒด์— name ์†์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ assemble ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

function assemble(param: Avengers) {
  console.log(param.name);
}

assemble(capt); // 'Captain' (ํƒ€์ž… ํ˜ธํ™˜)

 

ํƒ€์ž… ํ˜ธํ™˜ ์˜ˆ์ œ


Interface / Class (๊ฐ์ฒด ์†์„ฑ)

๐Ÿ’ก interface / class / ๊ฐ์ฒด ๋“ฑ์—์„œ ํ• ๋‹น ์—ฐ์‚ฐ์ž์˜ ์šฐํ•ญ(ๅณ้กน)์ด ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ํฌ๋‹ค๋ฉด ํƒ€์ž…์€ ํ˜ธํ™˜๋  ์ˆ˜ ์žˆ๋‹ค.

 

์•„๋ž˜ developer = person ์ฝ”๋“œ์—์„œ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋Š” person ํƒ€์ž…์„ developer์— ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค(ํƒ€์ž… ํ˜ธํ™˜ ๋ถˆ๊ฐ€). developer์—์„œ ํ•„์š”ํ•œ skill ์†์„ฑ์„ person์ด ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰, ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ์ž‘์€ person์„ developer์— ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•ด์„œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋‹ค.

interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
}

let developer: Developer;
let person: Person;

developer = person; // Error! ํƒ€์ž… ํ˜ธํ™˜ ๋ถˆ๊ฐ€
// TS2741: Property 'skill' is missing in type 'Person' but required in type 'Developer'.

person = developer; // ok ํƒ€์ž… ํ˜ธํ™˜

 

Person ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํด๋ž˜์Šค๋กœ ๋ฐ”๊ฟ”๋„ ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํƒ€์ž… ํ˜ธํ™˜์„ ๊ฒ€์ฆํ•  ๋•Œ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ์†์„ฑ๊ณผ ํƒ€์ž…์— ๋Œ€ํ•ด์„œ๋งŒ ๋น„๊ตํ•œ๋‹ค. interface, type, class ๋“ฑ์€ ์ƒ๊ด€์—†๋‹ค.

interface Developer {
  name: string;
  skill: string;
}

class Person {
  name: string;
}

let developer: Developer;
let person: Person;

developer = new Person(); // Error! ํƒ€์ž… ํ˜ธํ™˜ ๋ถˆ๊ฐ€
// TS2741: Property 'skill' is missing in type 'Person' but required in type 'Developer'.

 

Function / Generic (ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ)

๐Ÿ’ก function / generic ์—์„œ ํ• ๋‹น ์—ฐ์‚ฐ์ž์˜ ์ขŒํ•ญ(ๅทฆ้กน)์ด ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ํฌ๋‹ค๋ฉด ํƒ€์ž…์€ ํ˜ธํ™˜๋  ์ˆ˜ ์žˆ๋‹ค.

 

์•„๋ž˜ ์˜ˆ์‹œ์—์„œ sum์„ add์— ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค(ํƒ€์ž… ํ˜ธํ™˜ ๋ถˆ๊ฐ€). add๋Š” 1๊ฐœ ์ธ์ž๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ sum์€ 2๊ฐœ ์ธ์ž๋ฅผ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค(sum์ด add๋ณด๋‹ค ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ํฌ๋‹ค). interface / class ๋“ฑ๊ณผ๋Š” ๋ฐ˜๋Œ€๋กœ ํ• ๋‹น๋˜๋Š” ๊ฐ’(ํ• ๋‹น ์—ฐ์‚ฐ์ž์—์„œ ์šฐํ•ญ)์ด ๊ตฌ์กฐ์ ์œผ๋กœ ๋” ์ž‘์•„์•ผ ํƒ€์ž…์ด ํ˜ธํ™˜๋œ๋‹ค.

let add = function (a: number) {};
let sum = function (a: number, b: number) {};

add = sum; // Error! ํƒ€์ž… ํ˜ธํ™˜ ๋ถˆ๊ฐ€
// TS2322: Type '(a: number, b: number) => void' is not assignable to type '(a: number) => void'.

sum = add; // ok ํƒ€์ž… ํ˜ธํ™˜

 

์ œ๋„ค๋ฆญ์—์„  ํƒ€์ž… ์ธ์ž <T>๊ฐ€ ์†์„ฑ์— ํ• ๋‹น๋๋Š”์ง€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํƒ€์ž… ํ˜ธํ™˜ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์— ์•„๋ฌด๋Ÿฐ ์†์„ฑ๋„ ์—†๋‹ค๋ฉด ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

interface Empty<T> {}

let x: Empty<number>;
let y: Empty<string>;

x = y; // OK, because y matches structure of x

 

์ธํ„ฐํŽ˜์ด์Šค์— ์†์„ฑ(๋ฉค๋ฒ„ ๋ณ€์ˆ˜)์ด ์žˆ๊ณ , ์ œ๋„ค๋ฆญ์˜ ํƒ€์ž… ์ธ์ž๊ฐ€ ํ• ๋‹น๋˜์—ˆ๋‹ค๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

interface NotEmpty<T> {
  data: T;
}

let x: NotEmpty<number>;
let y: NotEmpty<string>;

x = y; // Error! because x and y are not compatible

 

๊ธฐํƒ€ ์ฐธ๊ณ  ๋‚ด์šฉ


์ด๋„˜ ํƒ€์ž…์€ number ํƒ€์ž…๊ณผ ํ˜ธํ™˜๋˜์ง€๋งŒ, ๊ฐ™์€ ์ด๋„˜ ํƒ€์ž…๋ผ๋ฆฌ๋Š” ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค

enum Status {
  Ready,
  Waiting,
}

enum Color {
  Red,
  Blue,
  Green,
}

let status = Status.Ready;
status = Color.Green; // Error! TS2322: Type 'Color.Green' is not assignable to type 'Status'.

 

ํด๋ž˜์Šค ํƒ€์ž…์€ ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„(ํ”„๋กœํผํ‹ฐ)๋“ค์„ ๋น„๊ตํ•œ๋‹ค. static ๋ฉค๋ฒ„์™€ ์ƒ์„ฑ์ž๋Š” ๋น„๊ต ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋œ๋‹ค. 

class Hulk {
  handSize: number; // ์†์„ฑ
  constructor(name: string, numHand: number) {}
}

class Captain {
  handSize: number; // ์†์„ฑ
  constructor(numHand: number) {}
}

let a: Hulk;
let b: Captain;

a = b; // ok
b = a; // ok

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ์ถ”๋ก ํ•  ์ˆ˜ ์—†๋Š” ํƒ€์ž…๋“ค์„ ์ผ๋‹จ ์•ˆ์ „ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ํŠน์„ฑ ๋•Œ๋ฌธ์— ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ํƒ€์ž… ์‹œ์Šคํ…œ์€ ์™„์ „ํžˆ "sound"(์•ˆ์ „ํ•œ) ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์—ฌ๊ฒจ์ง„๋‹ค. "sound" ์šฉ์–ด๋Š” ํƒ€์ž… ์‹œ์Šคํ…œ์ด ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ํƒ€์ž… ์˜ค๋ฅ˜๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฒ€์ถœํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ์‚ฌ์šฉ๋˜๋ฉฐ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ์ด๋Ÿฐ ๋ฉด์—์„œ ์–ด๋Š ์ •๋„ ํ•œ๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋Š” ์ ์„ ์ธ์ง€ํ•ด์•ผ ํ•œ๋‹ค. 

 

๋ ˆํผ๋Ÿฐ์Šค


ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ž…๋ฌธ - ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‹ค์ „๊นŒ์ง€ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜  

 


๊ธ€ ์ˆ˜์ •์‚ฌํ•ญ์€ ๋…ธ์…˜ ํŽ˜์ด์ง€์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”
๋ฐ˜์‘ํ˜•