๋ฐ˜์‘ํ˜•

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ž€?


ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์— ํƒ€์ž…์„ ๋ถ€์—ฌํ•œ ์–ธ์–ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ™•์žฅ๋œ ์–ธ์–ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰ํ•˜๋ ค๋ฉด ํŒŒ์ผ์„ ํ•œ ๋ฒˆ ๋ณ€ํ™˜ํ•ด์ค˜์•ผ ํ•œ๋‹ค. ์ด ๋ณ€ํ™˜ ๊ณผ์ •์„ ์ปดํŒŒ์ผ(์ •ํ™•ํžˆ๋Š” ํŠธ๋žœ์ŠคํŒŒ์ผ๋ง)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ฐธ๊ณ ๋กœ Babel์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ตœ์‹  ๋ฌธ๋ฒ•์„ ์ตœ๋Œ€ํ•œ ๋งŽ์€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ˜ธํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ๋„๊ตฌ๋‹ค.
 

์™œ ์จ์•ผ ํ• ๊นŒ?


์•„๋ž˜ 2๊ฐ€์ง€ ๊ด€์ ์—์„œ JS ์ฝ”๋“œ ํ’ˆ์งˆ๊ณผ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

  • ์—๋Ÿฌ ์‚ฌ์ „ ๋ฐฉ์ง€
  • ์ฝ”๋“œ ๊ฐ€์ด๋“œ ๋ฐ ์ž๋™ ์™„์„ฑ(์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ)
     

์—๋Ÿฌ ์‚ฌ์ „ ๋ฐฉ์ง€

์•„๋ž˜ ๋‘ ์ฝ”๋“œ ๋ชจ๋‘ ๋‘ ์ˆซ์ž์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜๋‹ค. ์œ„๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ, ์•„๋ž˜๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์—ด์„ ๋„ฃ์œผ๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ฌธ์ž์—ด์„ ๊ฒฐํ•ฉํ•ด์„œ ์ „ํ˜€ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

์•„๋ž˜๋Š” ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ผ์„œ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š์ง€๋งŒ, ์ฝ”๋“œ์–‘์ด ๋งŽ์•„์ง€๊ณ  ํฐ ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ ์ด๋Ÿฐ ์‚ฌ์†Œํ•œ ์˜ค๋ฅ˜๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ๋งŽ์€ ์‹œ๊ฐ„์„ ์Ÿ์•„์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ฐ˜๋ฉด ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๋ฌธ์ž์—ด์„ ๋„ฃ์œผ๋ฉด ๋ช…ํ™•ํ•œ ํƒ€์ž… ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋˜์ง€๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„์น˜ ์•Š์€ ์ฝ”๋“œ ๋™์ž‘์„ ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

function sum(a, b) {
  return a + b;
}

sum(10, 20); // 30
sum(10, '20'); // 1020

 

ํƒ€์ž…์ด ์ง€์ •๋ผ ์žˆ์ง€ ์•Š๋‹ค(any)

function sum(a: number, b: number) {
  return a + b;
}

sum(10, 20); // 30
sum(10, '20'); // Error

 

๋ช…ํ™•ํ•œ ํƒ€์ž…์ด ์ง€์ •๋ผ์žˆ๋‹ค(number)

 

์ฝ”๋“œ ์ž๋™ ์™„์„ฑ

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ์—์„œ sum() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๋‘ ์ˆซ์ž์˜ ํ•ฉ์„ ๊ตฌํ•œ ๊ฒฐ๊ณผ๋ฅผ result ๋ณ€์ˆ˜์— ๋‹ด๊ณ , result. ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด(์ฝค๋งˆ๊นŒ์ง€) ํ•ด๋‹น ํƒ€์ž…์—์„œ ์ œ๊ณตํ•˜๋Š” API ๋ชฉ๋ก์ด ์ž๋™์œผ๋กœ ๋‚˜์˜จ๋‹ค.

 

Number ํƒ€์ž…์˜ API ๋ชฉ๋ก ํ™”๋ฉด. tab๋งŒ ๋ˆ„๋ฅด๋ฉด ์ž๋™์™„์„ฑ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํŽธํ•˜๋‹ค.

 

๋ฐ˜๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํƒ€์ž…์ด ์ •ํ•ด์ ธ ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— API ์ด๋ฆ„์„ ์ผ์ผ์ด ์ž…๋ ฅํ•ด์•ผ ํ•œ๋‹ค. API ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๋Š” ๊ณผ์ •์—์„œ ์˜คํƒˆ์ž๋ฅผ ๋ƒˆ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋งŒ ์˜ค๋ฅ˜๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฒˆ๊ฑฐ๋กญ๋‹ค.
 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์ฒ˜๋Ÿผ ์“ฐ๋Š” ๋ฐฉ๋ฒ•


JSDoc์„ ์ด์šฉํ•˜๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋„ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์™€ ๋น„์Šทํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ /** ๋ถ€๋ถ„์ด JSDoc์ด๋ฉฐ ์—ฌ๊ธฐ์— ํƒ€์ž…์„ ๋ฏธ๋ฆฌ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

/**
 *
 * @param {number} a ์ฒซ๋ฒˆ์งธ ์ˆซ์ž
 * @param {number} b ๋‘๋ฒˆ์งธ ์ˆซ์ž
 */

function sum(a, b) {
  return a + b;
}

 

sum ํ•จ์ˆ˜์— ๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ์นœ์ ˆํ•˜๊ฒŒ ์ฒซ๋ฒˆ์งธ ์ˆซ์ž, ๋‘๋ฒˆ์งธ ์ˆซ์ž ์ž…๋ ฅํ•ด๋‘” ๊ฒƒ๊นŒ์ง€ ๋‚˜์˜จ๋‹ค. ํ•˜์ง€๋งŒ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์ฒ˜๋Ÿผ ํƒ€์ž…์„ ์ฒดํฌํ•˜์ง„ ์•Š๋Š”๋‹ค(๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•ด๋„ ์•„๋ฌด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค).

 

 

// @ts-check ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด TS์ฒ˜๋Ÿผ ํƒ€์ž…์ฒดํฌ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ด๋ ‡๊ฒŒ ํƒ€์ž… ์ฒดํฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งค๋ฒˆ JSDoc์— ์ผ์ผ์ด ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กœ์šด ์ผ์ด๋‹ค. ์ž‘์„ฑํ•œ ํƒ€์ž…์„ importํ•ด์„œ ์žฌํ™œ์šฉํ•  ์ˆ˜๋„ ์—†๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ด๋Ÿฐ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
 

ํƒ€์ž…


ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ธฐ๋ณธ ํƒ€์ž… 12๊ฐ€์ง€. ๋ฌธ์ž์—ด, ๋ทธ๋Ÿฐ, ๋„˜๋ฒ„ ๊ฐ™์€ ์›์‹œํƒ€์ž…์€ ๋Œ€๋ถ€๋ถ„ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์ถ”๋ก ํ•ด์ฃผ๋ฏ€๋กœ ์‹ค๋ฌด์—์„  ํƒ€์ž…์„ ๋ช…์‹œํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

 

  1. BOOLEAN
  2. NUMBER
  3. STRING
  4. OBJECT
  5. ARRAY
  6. TUPLE : ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๊ณ , ๊ฐ ์š”์†Œ์˜ ํƒ€์ž…์ด ์ง€์ •๋˜์–ด ์žˆ๋Š” ๋ฐฐ์—ด ํ˜•์‹
  7. ENUM : ํŠน์ • ๊ฐ’(์ƒ์ˆ˜)๋“ค์˜ ์ง‘ํ•ฉ(์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—” ์—†์Œ)
  8. ANY : ๋ชจ๋“  ํƒ€์ž… ํ—ˆ์šฉ(JS → TS ์ ์ง„์ ์œผ๋กœ ์ ์šฉํ•  ๋•Œ ํ™œ์šฉํ•˜๋ฉด ์ข‹์Œ)
  9. VOID : ๋ณ€์ˆ˜์—๋Š” undefined null๋งŒ ํ• ๋‹นํ•˜๊ณ  ํ•จ์ˆ˜์—๋Š” ๋ฐ˜ํ™˜๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์—†๋Š” ํƒ€์ž…. ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋‹ค๊ณ  ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋Š” ๊ฒƒ. ํ•จ์ˆ˜์—์„œ ๋ฆฌํ„ด ๊ฐ’์ด ์—†์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
  10. NULL
  11. UNDEFINED
  12. NEVER : ์–ด๋–ค ํƒ€์ž…๊ณผ๋„ ํ˜ธํ™˜ํ•˜์ง€ ์•Š๋Š” ํƒ€์ž…. ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋๊นŒ์ง€ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์€ never ํƒ€์ž…์ด ๋œ๋‹ค. if๋ฌธ ๋“ฑ์œผ๋กœ ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ์ขํ˜€์ง„ ๋ณ€์ˆ˜๋Š” never ํƒ€์ž…์ด ๋  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ ๋นˆ ๋ฐฐ์—ด์„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ never[]๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
     

UNKNOWN ํƒ€์ž…

unknown ํƒ€์ž…์€ any์ฒ˜๋Ÿผ ๋ชจ๋“  ํƒ€์ž…์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ํƒ€์ž…์„ ์ขํ˜€์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์˜๋ฌด๊ฐ€ ์žˆ๋Š” ์ ์ด any์™€ ๋‹ค๋ฅด๋‹ค. ๋•Œ๋ฌธ์— ํƒ€์ž… ๋‹จ์–ธ์ด๋‚˜ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž…์„ ์ขํ˜€์ค˜์•ผ ํ•œ๋‹ค. — ์ฐธ๊ณ  ๋งํฌ

 

unknown ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜์— ํ• ๋‹น๋  ์ˆ˜ ์—†๋‹ค(any๋Š” ๊ฐ€๋Šฅ).

let sayHello: unknown;
sayHello = 'Hello World';

const sayHi: string = sayHello; // 'unknown' ํ˜•์‹์€ 'string' ํ˜•์‹์— ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.ts(2322)
const sayHi: string = sayHello as string; // string์œผ๋กœ ํƒ€์ž… ๋‹จ์–ธํ•ด์„œ ํ• ๋‹น ๊ฐ€๋Šฅ
const sayHi: any = sayHello; // any ํƒ€์ž…์ด๋ผ์„œ ํ• ๋‹น ๊ฐ€๋Šฅ

const printConsole = (params: string) => {
  console.log(params);
};

printConsole(hello); // 'unknown' ํ˜•์‹์˜ ์ธ์ˆ˜๋Š” 'string' ํ˜•์‹์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ํ• ๋‹น๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.ts(2345)
printConsole(hello as string); // 'Hello World'

 

unknown ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค. ์ธ์Šคํ„ด์Šค ์—ญ์‹œ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.

const fkj: unknown = {
  title: 'Before Chill',
  genre: 'Jazz Hiphop',
};

fkj.title // ๊ฐœ์ฒด๊ฐ€ '์•Œ ์ˆ˜ ์—†๋Š”' ํ˜•์‹์ž…๋‹ˆ๋‹ค.ts(2571)

const abc: unknown = ['a', 'b', 'c'];
abc[0] // ๊ฐœ์ฒด๊ฐ€ '์•Œ ์ˆ˜ ์—†๋Š”' ํ˜•์‹์ž…๋‹ˆ๋‹ค.ts(2571)

const abc: unknown = () => {
  console.log('hello');
};

abc();// ๊ฐœ์ฒด๊ฐ€ '์•Œ ์ˆ˜ ์—†๋Š”' ํ˜•์‹์ž…๋‹ˆ๋‹ค.ts(2571)

 

๐Ÿ’ก ๊ธฐ์กด ํƒ€์ž…์„ ๋ฌด์‹œํ•˜๊ณ , ๊ฐ•์ œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์„ ์ง€์ •ํ•ด์•ผ ํ•  ๋•Œ(ํƒ€์ž… ์บ์ŠคํŒ…) `unknown`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

... as unknown as ์›ํ•˜๋Š”ํƒ€์ž…

 

๋ฌธ์ž์—ด / ์ˆซ์ž / ๋ฐฐ์—ด

๐Ÿ’ก `:` ๋ฅผ ์ด์šฉํ•ด ํƒ€์ž…์„ ์ •์˜ ํ•˜๋Š” ๋ฐฉ์‹์„ Type Annotation์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ํƒ€์ž…์„ ์ •์˜ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์— ํƒ€์ž…์„ ์ž…ํ˜€์ฃผ๋Š” ํ–‰์œ„๋ฅผ ํƒ€์ดํ•‘(typing)์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

// ๋ฌธ์ž์—ด, ์ˆซ์ž ์ •์˜
const str: string = 'hello'; // ๋ฌธ์ž์—ด ํƒ€์ž… ์ •์˜
const num: number = 10; // ๋„˜๋ฒ„ ํƒ€์ž… ์ •์˜

// ๋ฐฐ์—ด ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ•1 (Array๋Š” ๋Œ€๋ฌธ์ž๋กœ ์ ์–ด์•ผ๋˜๋Š” ์  ์ฃผ์˜)
const arr: Array<number> = [1, 2, 3]; // ๋„˜๋ฒ„๋งŒ ๊ฐ€๋Šฅ
const heroes: Array<string> = ['Capt', 'Thor', 'Hulk']; // ๋ฌธ์ž์—ด๋งŒ ๊ฐ€๋Šฅ

// ๋ฐฐ์—ด ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ•2
const items: number[] = [1, 2, 3];

 

  1. String / Nuber ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ• : const ๋ณ€์ˆ˜๋ช…: ํƒ€์ž…๋ช… = 'value'
  2. Array ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ• 2๊ฐ€์ง€ — Array๋Š” string number์™€ ๋‹ค๋ฅด๊ฒŒ ๋Œ€๋ฌธ์ž๋กœ ์ ์–ด์•ผ ๋˜๋Š” ์  ์ฃผ์˜
    • ๊ธฐ๋ณธ(์ œ๋„ค๋ฆญ) : const ๋ณ€์ˆ˜๋ช…: Array<ํƒ€์ž…๋ช…> = [...]
    • ์ถ•์•ฝ : const ๋ณ€์ˆ˜๋ช…: ํƒ€์ž…๋ช…[] = [...]
       

ํŠœํ”Œ / ๊ฐ์ฒด / ๋ทธ๋Ÿฐ

// TS ํŠœํ”Œ(๋ฐฐ์—ด์˜ ํŠน์ • ์ธ๋ฑ์Šค๊นŒ์ง€ ํƒ€์ž… ์ง€์ •)
const address: [string, number] = ['gangnam', 100];

// ๊ฐ์ฒด ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ•1 (ESLint ๋น„์ถ”์ฒœ)
const person: object = {
  name: 'John',
  age: 100,
};

// ๊ฐ์ฒด ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ•2 (ESLint ์ถ”์ฒœ)
const person: Record<string, unknown> = {
  name: 'John',
  age: 100,
};

// ๊ฐ์ฒด ๊ฐ ์†์„ฑ์— ๋Œ€ํ•œ ํƒ€์ž… ๋ณ„๋„ ์ง€์ •
const person: { name: string; age: number } = {
  name: 'John', // name ์†์„ฑ์€ string๋งŒ ๊ฐ€๋Šฅ
  age: 100, // age ์†์„ฑ์€ number๋งŒ ๊ฐ€๋Šฅ
};

// ๋ทธ๋Ÿฐ ํƒ€์ž… ์ •์˜
const show: boolean = true;

 

  1. Tuple ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ• — Tuple์€ ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๊ณ , ๊ฐ ์š”์†Œ์˜ ํƒ€์ž…์ด ์ง€์ •๋œ ๋ฐฐ์—ด ํ˜•์‹
    • const ๋ณ€์ˆ˜๋ช…: [ํƒ€์ž…, ํƒ€์ž…] = [...]
    • const RGB: [red: number, green: number, blue: number] = [255, 0, 0]
  2. Object ํƒ€์ž… ์ •์˜ ๋ฐฉ๋ฒ• 3๊ฐ€์ง€ โญ๏ธ
    • ๊ธฐ๋ณธ: const ๋ณ€์ˆ˜๋ช…: object = {...}
    • ESLint ์ถ”์ฒœ ๋ฐฉ๋ฒ•: const ๋ณ€์ˆ˜๋ช…: Record<string, unknown> = {...}
      value ๋ถ€๋ถ„์— ์–ด๋–ค ํƒ€์ž…์ด ์˜ฌ์ง€ ๋ชจ๋ฅธ๋‹ค๋ฉด unknown, ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ํ•ด๋‹นํ•˜๋Š” type ๋ช…์‹œ
    • ๊ฐ์ฒด ๊ฐ ์†์„ฑ์— ๋Œ€ํ•œ ํƒ€์ž… ์ง€์ •: const ๋ณ€์ˆ˜๋ช…: { key: ํƒ€์ž… } = {...}
  3. Boolean ํƒ€์ž… ์ •์˜ : const ๋ณ€์ˆ˜๋ช…: boolean = true ํ˜น์€ false 

 

ํ•จ์ˆ˜ ๊ธฐ๋ณธ

๐Ÿ’ก ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’์— ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š์„ ๋•Œ๋Š” `void` ๋ผ๋„ ์‚ฌ์šฉํ•œ๋‹ค

 

function sum(a: number, b: number): number {
  return a + b;
}

 

  • ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ์ง€์ • : function sum(์ธ์ž: ์ธ์žํƒ€์ž…) {...}
  • ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’ ํƒ€์ž… ์ง€์ • : function sum(์ธ์ž: ์ธ์žํƒ€์ž…): ๋ฐ˜ํ™˜ํƒ€์ž… {...}

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  ํ•จ์ˆ˜์˜ ์ธ์ž๋ฅผ ๋ชจ๋‘ ํ•„์ˆ˜ ๊ฐ’์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ–ˆ๋‹ค๋ฉด undefined ๋‚˜ null ์ด๋ผ๋„ ์ธ์ž๋กœ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค.

 

๋งŒ์•ฝ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ 2๊ฐœ๋กœ ์ง€์ •ํ–ˆ์ง€๋งŒ ํ•จ์ˆ˜ ํ˜ธ์ถœ์‹œ ์ธ์ž๋ฅผ 3๊ฐœ ์ด์ƒ์„ ๋„ฃ์œผ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ts(2554) ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜์˜จ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์ด ์ƒํ™ฉ์—์„œ ์•„๋ฌด๋Ÿฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฟœ์ง€ ์•Š๋Š”๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  VSCode๊ฐ€ ํ•จ์ˆ˜์˜ ์ŠคํŽ™์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋” ์—„๊ฒฉํ•˜๊ฒŒ ์ฒดํฌํ•˜๋Š” ๊ฒƒ.

 

 

ํ•จ์ˆ˜์˜ ์„ ํƒ์  ํŒŒ๋ผ๋ฏธํ„ฐ

์ •์˜ํ•œ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ชจ๋‘ ํ•„์š”ํ•  ๋•Œ๋„ ์žˆ๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ? ๋ฌผ์Œํ‘œ๋ฅผ ์ด์šฉํ•˜๋ฉด ์„ ํƒ์  ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ผ์„œ ์ •์˜ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐœ์ˆ˜๋งŒํผ ์ธ์ž๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค(? ์ธ์ž๋Š” ๋„ฃ์–ด๋„ ๋˜๊ณ  ์•ˆ๋„ฃ์–ด๋„ ๋œ๋‹ค).

// ํ•จ์ˆ˜์˜ ์˜ต์…”๋„(์„ ํƒ์ ) ํŒŒ๋ผ๋ฏธํ„ฐ
function log(a: number, b?: number): number {
  return b ? a + b : a;
}

log(10); // 10
log(10, 20); // 30

 

์•„๋ž˜์ฒ˜๋Ÿผ ํŒŒ๋ผ๋ฏธํ„ฐ์— Partial<์ธํ„ฐํŽ˜์ด์Šค_์ด๋ฆ„> ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ? ๋ฌผ์Œํ‘œ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ ์ค‘ ์ผ๋ถ€๋งŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š”๋‹ค๋Š” ๋œป.

// User ํƒ€์ž…
interface User {
  email: string;
  id: number;
}

function updateMe(user: Partial<User>): AxiosPromise<{ data: User }> {
  return axios.patch('/me', { ...user });
}

 

ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”

๋งค๊ฐœ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”๋Š” ES6 ๋ฌธ๋ฒ•๊ณผ ๋™์ผํ•˜๊ฒŒ function log(a = 'Hello') {...} ํ˜•์‹์œผ๋กœ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.

// ๋งค๊ฐœ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”
function log(a = 'Hello', b?: string): string {
  return `${a} ${b}`;
}

log(undefined, 'World'); // Hello World

 

REST ๋ฌธ๋ฒ•์ด ์ ์šฉ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ES6์˜ REST ๋ฌธ๋ฒ•์€ ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. REST ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ํŒŒ๋ผ๋ฏธํ„ฐ์— ...์ธ์ž์ด๋ฆ„: ํƒ€์ž…๋ช…[] ํ˜•์‹์œผ๋กœ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.

// Rest ๋ฌธ๋ฒ• ์ ์šฉ
function sum(a: number, ...nums: number[]): number {
  console.log(nums); // [2, 3, 4]

  const totalOfNums = nums.reduce((acc, cur) => acc + cur, 0);
  return a + totalOfNums;
}

sum(1, 2, 3, 4); // 10

 

this์™€ ์ฝœ๋ฐฑ

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ this์˜ ํƒ€์ž…์„ ๋ช…์‹œํ•˜๋ ค๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.

function ํ•จ์ˆ˜๋ช…(this: ํƒ€์ž…) {
  // ์ƒ๋žต
}

 

์ผ๋ฐ˜ this ์‚ฌ์šฉ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์ฝœ๋ฐฑ์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ–ˆ์„ ๋• this๋ฅผ ๊ตฌ๋ถ„ํ•ด์ค˜์•ผ ํ•œ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

interface UIElement {
  // ์•„๋ž˜ ํ•จ์ˆ˜์˜ `this: void` ์ฝ”๋“œ๋Š” ํ•จ์ˆ˜์— `this` ํƒ€์ž…์„ ์„ ์–ธํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ์˜๋ฏธ.
  addClickListener(onclick: (this: void, e: Event) => void): void;
}

class Handler {
  info: string;

  onClick(this: Handler, e: Event) {
    // `UIElement` ์ธํ„ฐํŽ˜์ด์Šค ์ŠคํŽ™์— `this`๊ฐ€ ํ•„์š”์—†๋‹ค๊ณ  ํ–ˆ์ง€๋งŒ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ ๋ฐœ์ƒ.
    this.info = e.message;
  }
}

const handler = new Handler();
uiElement.addClickListener(handler.onClick); // error!

 

UIElement ์ธํ„ฐํŽ˜์ด์Šค ์ŠคํŽ™์— ๋งž์ถฐ Handler๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค.

class Handler {
  info: string;

  onClick(this: void, e: Event) {
    // `this` ํƒ€์ž…์ด void์ด๋ฏ€๋กœ ์—ฌ๊ธฐ์„  `this`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค
    console.log('clicked!');
  }
}

const handler = new Handler();
uiElement.addClickListener(handler.onClick);

 

ts(2330) ์—๋Ÿฌ

์•„๋ž˜ ์ฝ”๋“œ์—์„œ todo ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํƒ€์ž…์„ object๋กœ ๋ช…์‹œํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ todo.done ์—์„œ done ์†์„ฑ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ts(2330) ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋ช…์‹œํ•œ object ํƒ€์ž…์•ˆ์— ์–ด๋–ค ์†์„ฑ์ด ์žˆ๋Š”์ง€ VSCode๋Š” ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ฟœ๋Š” ์—๋Ÿฌ๋‹ค.

function completeTodo(index: number, todo: object): void {
  todo.done = true; // ts(2330) ์—๋Ÿฌ!
}

 

 

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„  todo ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ์ฒด ํƒ€์ž…์— ์–ด๋–ค ์†์„ฑ์„ ํฌํ•จํ•˜๋Š”์ง€ ๊ตฌ์ฒด์ ์œผ๋กœ ๋ช…์‹œํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

function completeTodo(
  index: number,
  todo: {
    id: number;
    title: string;
    done: boolean;
  },
): void {
  todo.done = true;
}

 

์œ„์—์„œ ์ •์˜ํ•œ ํƒ€์ž…์„ ์•ž์œผ๋กœ๋„ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๋งค๋ฒˆ ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด ์†์„ฑ์„ ๋ช…์‹œํ•˜๊ธฐ ๋ฒˆ๊ฑฐ๋กญ๊ธฐ ๋•Œ๋ฌธ์— type ํ˜น์€ interface๋กœ ํƒ€์ž…์„ ๋ฏธ๋ฆฌ ์ •์˜ํ•œ ํ›„ ๋ณ€์ˆ˜๋ช…์œผ๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

interface Todo {
  id: number;
  title: string;
  done: boolean;
}

function completeTodo(index: number, todo: Todo): void {
  todo.done = true; 
}

 

์ธํ„ฐํŽ˜์ด์Šค


์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ƒํ˜ธ ๊ฐ„ ์ •์˜ํ•œ ์•ฝ์† ํ˜น์€ ๊ทœ์น™์„ ์˜๋ฏธํ•œ๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฒ”์ฃผ์— ๋Œ€ํ•ด ์•ฝ์†์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • ๊ฐ์ฒด์˜ ์ŠคํŽ™(์†์„ฑ๊ณผ ์†์„ฑ์˜ ํƒ€์ž…)
  • ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ
  • ํ•จ์ˆ˜์˜ ์ŠคํŽ™(ํŒŒ๋ผ๋ฏธํ„ฐ, ๋ฐ˜ํ™˜ ํƒ€์ž… ๋“ฑ)
  • ๋ฐฐ์—ด๊ณผ ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹
  • ํด๋ž˜์Šค
     

๊ธฐ๋ณธ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜ํ•œ ์†์„ฑ์„ ๋ชจ๋‘ ์ ์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ์†์„ฑ, ํƒ€์ž… ์กฐ๊ฑด๋งŒ ๋งŒ์กฑํ•œ๋‹ค๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋„˜๊ธฐ๋Š” ์†์„ฑ ๊ฐฏ์ˆ˜๊ฐ€ ๋” ๋งŽ์•„๋„ ์ƒ๊ด€์—†๋‹ค.

interface User {
  age: number;
  name: string;
}

// ๋ณ€์ˆ˜์— ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ
const smith: User = {
  age: 33,
  name: 'smith',
};

// ํ•จ์ˆ˜์— ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ
function getUser(user: User): User {
  return user;
}

getUser({
  age: 28,
  name: 'John', // ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜ํ•œ ์†์„ฑ์„ ๋‹ค ์ ์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค
});

// User ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ฐ์ฒด๋ฅผ ์š”์†Œ๋กœ ๊ฐ–๋Š” users ๋ฐฐ์—ด ์„ ์–ธ
const users: User[]; // [{...}, {...}]

 

ํ•จ์ˆ˜ ์ธ์ž๋ฅผ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค

์•„๋ž˜์™€ ๊ฐ™์€ ํ•จ์ˆ˜ ์ฝ”๋“œ์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ ์šฉํ•˜๋ฉด...

let Capt = { name: 'Capt', age: 28 };

function logAge(obj: { age: number }) {
  console.log(obj.age); // 28
}

logAge(Capt);

 

์•„๋ž˜์ฒ˜๋Ÿผ ๋œ๋‹ค. logAge() ์ธ์ž๊ฐ€ ์ข€ ๋” ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค. logAge() ํ•จ์ˆ˜์˜ ์ธ์ž๋Š” PersonAge์—์„œ ์ •์˜ํ•œ ํƒ€์ž… ์†์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์—์„œ name ์†์„ฑ์€ ์ •์˜ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ obj.name ์ฝ˜์†”๋กœ๊ทธ๋Š” ts(2339)์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

// ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„์€ ๋ณดํ†ต PascalCase ์ง€์ •ํ•œ๋‹ค
interface PersonAge {
  age: number;
}

function logAge(obj: PersonAge): void {
  console.log(obj.age); // 28
  console.log(obj.name); // ts(2339) ์—๋Ÿฌ!
}

const Capt = { name: 'Capt', age: 28 };
logAge(Capt);

 

  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์‚ฌ์šฉํ•  ๋•Œ ํ•ญ์ƒ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜ํ•œ ์†์„ฑ ๊ฐฏ์ˆ˜์™€, ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ๊ฐ์ฒด์˜ ์†์„ฑ ๊ฐฏ์ˆ˜๋ฅผ ์ผ์น˜์‹œํ‚ค์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ์†์„ฑ, ํƒ€์ž… ์กฐ๊ฑด๋งŒ ๋งŒ์กฑํ•˜๋ฉด ๊ฐ์ฒด์˜ ์†์„ฑ ๊ฐฏ์ˆ˜๊ฐ€ ๋” ๋งŽ์•„๋„ ์ƒ๊ด€์—†๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ ์†์„ฑ ์ˆœ์„œ๋ฅผ ์ง€ํ‚ค์ง€ ์•Š์•„๋„ ๋œ๋‹ค. 

 

ํ•จ์ˆ˜์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค

์•„๋ž˜๋Š” ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ, ๋ฐ˜ํ™˜ ํƒ€์ž… ๋“ฑ์„ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์‹œ. ํŒ€ ํ”„๋กœ์ ํŠธ ๋“ฑ์—์„œ ํ•จ์ˆ˜์˜ ๊ทœ์น™์„ ๋ฏธ๋ฆฌ ์žก์•„๋†“๊ณ  ์ง„ํ–‰ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

// ํ•จ์ˆ˜์˜ ์ŠคํŽ™(๊ตฌ์กฐ)์— ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ
interface SumFunction {
  (a: number, b: number): number; // ํ•จ์ˆ˜ ์ธ์ž ๋ฐ ๋ฐ˜ํ™˜๊ฐ’ ์ •์˜
}

const sums: SumFunction = (a, b) => {
  return a + b;
};

sums(10, 20); // 30

 

์ธ๋ฑ์‹ฑ ๋ฐฉ์‹์„ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค

์•„๋ž˜ ์ฝ”๋“œ์—์„œ ๋ฐฐ์—ด์˜ index๋Š” ํ•ญ์ƒ ์ˆซ์ž์ด๊ณ  ๋ฐฐ์—ด ์š”์†Œ์˜ ํƒ€์ž…์€ string์ด๋ผ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐฐ์—ด์—” ๋ฌธ์ž์—ด ์š”์†Œ๋งŒ ์˜ฌ ์ˆ˜ ์žˆ๊ณ  ์ธ๋ฑ์‹ฑ ๋ฐฉ์‹์€ ์ˆซ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. array[0] = 10 ๊ฐ™์ด ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ•˜์ง€ ์•Š์€ ํƒ€์ž…์„ ํ• ๋‹น ํ•  ๊ฒฝ์šฐ ts(2332) ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.

interface StringArray {
  // ๋ฐฐ์—ด์˜ index๋Š” ํ•ญ์ƒ ์ˆซ์ž์ด๊ณ  ์š”์†Œ ํƒ€์ž…์€ string์ด๋ผ๊ณ  ์ •์˜
  [index: number]: string;
}

const array: StringArray = ['a', 'b', 'c'];
array[0] = 10; // ts(2332) error

 

์ธํ„ฐํŽ˜์ด์Šค ๋”•์…”๋„ˆ๋ฆฌ ํŒจํ„ด

๊ฐ์ฒด์˜ key๋Š” ๋ฌธ์ž์—ด, value๋Š” ์ •๊ทœ์‹์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ–ˆ๋‹ค. ๋งŒ์•ฝ ๊ฐ์ฒด ์ธ๋ฑ์Šค์— ์ •๊ทœ์‹์ด ์•„๋‹Œ ๋ฌธ์ž์—ด๋กœ ์ ‘๊ทผํ–ˆ๋‹ค๋ฉด ์ธํ„ฐํŽ˜์ด์Šค ๊ทœ์น™์— ์–ด๊ธ‹๋‚˜๋ฏ€๋กœ ts(2322) ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

// ๋”•์…”๋„ˆ๋ฆฌ ํŒจํ„ด
interface StringRegexDictionary {
  // key๋Š” ๋ฌธ์ž์—ด, value๋Š” ์ •๊ทœ์‹์œผ๋กœ ์ •์˜
  [key: string]: RegExp;
}

const obj: StringRegexDictionary = {
  cssFile: /\.css$/, // CSSํŒŒ์ผ๋กœ ๋๋‚˜๋Š” ํ™•์žฅ์ž
  jsFile: /\.js$/, // JSํŒŒ์ผ๋กœ ๋๋‚˜๋Š” ํ™•์žฅ์ž
  jsonFile: '.json', // ts(2322) error!
};

obj['cssFile'] = 'a'; // ts(2322) error!
Object.keys(obj).forEach(function (value) {
  /* ... */
});

 

๋”•์…”๋„ˆ๋ฆฌ ํŒจํ„ด์— ์˜ํ•ด obj๋ฅผ ์กฐ์ž‘ํ•  ๋•Œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํƒ€์ž…๊นŒ์ง€ ์ž๋™์œผ๋กœ ์ถ”๋ก ํ•ด์„œ ์ •์˜ํ•ด์ค€๋‹ค.

 

 

์ธํ„ฐํŽ˜์ด์Šค ํ™•์žฅ

OOP์˜ ์ƒ์†, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ”„๋กœํ† ํƒ€์ž…์ฒ˜๋Ÿผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ธฐ์กด ์†์„ฑ์„ ํ™•์žฅํ•ด์„œ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ค‘๋ณต๋œ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค์˜ ์†์„ฑ๊ณผ ํƒ€์ž…์„ ํ™•์žฅ๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅ๋ฐ›์•˜๋‹ค๋ฉด, ํ™•์žฅ ๋ฐ›์€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํƒ€์ž…๊นŒ์ง€ ๋ชจ๋‘ ์ •์˜ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

interface Person {
  name: string;
  age: number;
}

// Person ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Developer๋กœ ํ™•์žฅ
interface Developer extends Person {
  language: string;
}

// Person ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅ ๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— Person์— ์žˆ๋Š” ํƒ€์ž…๊นŒ์ง€ ๋ชจ๋‘ ์ •์˜ํ•œ๋‹ค
const john: Developer = {
  language: 'ts',
  age: 32,
  name: 'john',
};

 

๊ธฐํƒ€ ์ธํ„ฐํŽ˜์ด์Šค ํŠน์ง•

์˜ต์…˜ ์†์„ฑ : ์†์„ฑ ๋์— ? ๋ฌผ์Œํ‘œ๋ฅผ ๋ถ™์ด๋ฉด ํ•ด๋‹น ์†์„ฑ์„ ์„ ํƒ์ ์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ์†์„ฑ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ•˜์ง€ ์•Š์€ ์†์„ฑ์„ ์ธ์ง€์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ๋„ ์žˆ๋‹ค.

interface ์ธํ„ฐํŽ˜์ด์Šค_์ด๋ฆ„ {
  name: string;
  age?: number;
}

 

์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ : ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ฐ์ฒด๋ฅผ ์ฒ˜์Œ ์ฒ˜์Œ ์ƒ์„ฑํ•  ๋•Œ๋งŒ ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ , ๊ทธ ์ดํ›„์—” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ์†์„ฑ. readonly ์†์„ฑ์„ ์•ž์— ๋ถ™์ด๋ฉด ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์ด ๋œ๋‹ค.

interface RedWine {
  readonly brand: string;
}

const myWine: RedWine = {
  brand: 'Bordeaux'
};

myWine.brand = 'Korean Wine'; // error!

 

์ฝ๊ธฐ ์ „์šฉ ๋ฐฐ์—ด : ๋ฐฐ์—ด ์„ ์–ธ ์‹œ ReadonlyArray<ํƒ€์ž…๋ช…>์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ๊ธฐ ์ „์šฉ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ ์–ธํ•˜๋Š” ์‹œ์ ์—๋งŒ ๊ฐ’์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฃผ์˜ํ•˜์ž.

const arr: ReadonlyArray<number> = [1, 2, 3];
arr.slice(0, 1); // error
arr.push(4); // error

 

๊ฐ์ฒด ์„ ์–ธ๊ณผ ํƒ€์ž… ์ฒดํ‚น : ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•  ๋• ๋” ์—„๊ฒฉํ•œ ์†์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ RedWine ์ธํ„ฐํŽ˜์ด์Šค์—์„œ brand๋ผ๊ณ  ์„ ์–ธํ–ˆ์ง€๋งŒ whiteWine() ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ธฐ๋Š” ๊ฐ์ฒด ์†์„ฑ์€ brandon์œผ๋กœ ์„ ์–ธํ•ด์„œ ์˜คํƒˆ์ž ์ ๊ฒ€ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค.

interface RedWine {
  brand?: string;
}

function whiteWine(wine: RedWine): void {
  console.log(wine);
}

whiteWine({ brandon: "Syrah" }); // ts(2345) error!

 

์ด๋Ÿฐ ํƒ€์ž… ์ถ”๋ก ์„ ๋ฌด์‹œํ•˜๊ณ  ์‹ถ์œผ๋ฉด as ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

const myWine = { brandon: 'Syrah'};
whiteWine(myWine as RedWine);

 

๋งŒ์•ฝ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ•˜์ง€ ์•Š์€ ์†์„ฑ์„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, [propName: string]: any; ์ฝ”๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์— ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

interface RedWine {
  brand?: string;
  // key(propName)์˜ ํƒ€์ž…์€ string์ด๊ณ  value ํƒ€์ž…์€ any
  // [key: string]: any -> ์ด๋ ‡๊ฒŒ๋„ ๊ฐ€๋Šฅ
  [propName: string]: any;
}

 

ํƒ€์ž… ๋ณ„์นญ


ํƒ€์ž… ๋ณ„์นญ์€ ํŠน์ • ํƒ€์ž…์ด๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž… ๋ณ€์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

// ์ผ๋ฐ˜ string ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ
const name: string = 'John';

// ํƒ€์ž… ๋ณ„์นญ์„ ์‚ฌ์šฉํ•  ๋•Œ
type MyName = string;
const name: MyName = 'John';

 

interface ๋ ˆ๋ฒจ์˜ ๋ณต์žกํ•œ ํƒ€์ž…์—๋„ ๋ณ„์นญ์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

type Developer = {
  name: string;
  skill: string;
};

const john: Developer = {
  name: 'john',
  skill: 'JS',
};

 

ํƒ€์ž… ๋ณ„์นญ์— ์•„๋ž˜์ฒ˜๋Ÿผ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

type User<T> = {
  name: T;
};

const john: User<string> = {
  name: 'John',
};

 

ํƒ€์ž… ๋ณ„์นญ ํŠน์ง•

ํƒ€์ž… ๋ณ„์นญ์€ ์ƒˆ๋กœ์šด ํƒ€์ž… ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ •์˜ํ•œ ํƒ€์ž…์„ ๋‚˜์ค‘์— ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. cmd๋ฅผ ๋ˆ„๋ฅด๊ณ  ํƒ€์ž… ๋ณ„์นญ ํ˜น์€ ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ํƒ€์ž…์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

 

ํƒ€์ž… ๋ณ„์นญ์œผ๋กœ ์„ ์–ธํ•œ ํƒ€์ž…์˜ ํ”„๋ฆฌ๋ทฐ
์ธํ„ฐํŽ˜์ด์Šค๋กœ ์„ ์–ธํ•œ ํƒ€์ž…์˜ ํ”„๋ฆฌ๋ทฐ

 

ํƒ€์ž… / ์ธํ„ฐํŽ˜์ด์Šค ์ฐจ์ด์ 

๐Ÿ’ก ์ข‹์€ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์–ธ์ œ๋‚˜ ํ™•์žฅ์ด ์šฉ์ด ํ•ด์•ผํ•œ๋‹ค.

 

ํƒ€์ž… ๋ณ„์นญ๊ณผ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ํƒ€์ž…์˜ ํ™•์žฅ ๊ฐ€๋Šฅ / ๋ถˆ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ™•์žฅ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ํƒ€์ž… ๋ณ„์นญ์€ ํ™•์žฅํ•  ์ˆ˜ ์—†๋‹ค. ๋•Œ๋ฌธ์— interface๋กœ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š”๊ฑธ ์ถ”์ฒœํ•œ๋‹ค.
 

์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•œ ํƒ€์ž… ์ •์˜


์œ ๋‹ˆ์˜จ ํƒ€์ž…์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ OR ์—ฐ์‚ฐ์ž || ์ฒ˜๋Ÿผ Aํ˜น์€ B ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  | ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋ณ€์ˆ˜ ํ˜น์€ ํŒŒ๋ผ๋ฏธํ„ฐ์— 1๊ฐ€์ง€ ์ด์ƒ ํƒ€์ž…์„ ์„ ํƒ์ง€๋กœ ์“ฐ๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค.

 

์•„๋ž˜ logMessage ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์œ ๋‹ˆ์˜จ ํƒ€์ž… |์„ ์ ์šฉํ•˜์—ฌ string๊ณผ number ํƒ€์ž…์ค‘ ํ•œ ๊ฐ€์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ๋ณ€์ˆ˜์— ์ ์šฉํ•  ๋•Œ๋„ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์“ฐ๋ฉด ๋œ๋‹ค.

// ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— Union Type ์‚ฌ์šฉ
function logMessage(value: string | number): void {
  console.log(value);
}

logMessage('Hello');
logMessage(10);

// ๋ณ€์ˆ˜์— Union Type ์‚ฌ์šฉ
let jenny: string | number | boolean;

 

์œ ๋‹ˆ์˜จ ํƒ€์ž… ์žฅ์ 

any ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ํƒ€์ž…์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ž๋™์™„์„ฑ์ด ์•ˆ๋œ๋‹ค. ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ํ•ด๋‹น ํƒ€์ž…์— ํ•ด๋‹นํ•˜๋Š” API ์†์„ฑ์ด ์ž๋™์™„์„ฑ๋˜๋ฏ€๋กœ ํŽธ๋ฆฌํ•˜๋‹ค.

 

 

์•„๋ž˜ if๋ฌธ ์ฒ˜๋Ÿผ ํƒ€์ž…์˜ ๋ฒ”์œ„๋ฅผ ์ขํ˜€๋‚˜๊ฐ€๋Š”(ํ•„ํ„ฐ๋ง ํ•˜๋Š”) ๊ณผ์ •์„ ํƒ€์ž…๊ฐ€๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

function logMessage(value: string | number): string | number {
  if (typeof value === 'number') {
    // number์— ๋Œ€ํ•œ API ์†์„ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค
    return value.toLocaleString();
  }
  if (typeof value === 'string') {
    return value.toString();
  }
  // ์ •์˜ํ•˜์ง€ ์•Š์€ ํƒ€์ž…์ด ์˜ค๋ฉด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค
  throw new TypeError('value must be string or number');
}

logMessage('Hello'); // Hello
logMessage(10); // 10
logMessage([1, 2, 3]); // ts[2769] error! value must be string or number

 

์œ ๋‹ˆ์˜จ ํƒ€์ž… ํŠน์ง•

์•„๋ž˜ ์ฝ”๋“œ์—์„œ Developers์™€ Marketers ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“  ํ›„ askSomeone ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ์ด์šฉํ•ด 2๊ฐœ์˜ ํƒ€์ž…์„ ์ •์˜ํ–ˆ๋‹ค. 2๊ฐœ์˜ ํƒ€์ž…์„ ๋ชจ๋‘ ์ ์šฉํ–ˆ์œผ๋‹ˆ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ๊ฐ€์ง€๋Š” ๋ชจ๋“  ์†์„ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๋Š” name ์†์„ฑ์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

 

ํ•จ์ˆ˜ ํ˜ธ์ถœ์‹œ์—๋„ ๋‘ ์ธํ„ฐํŽ˜์ด์Šค ๊ณตํ†ต ์†์„ฑ ์™ธ์—, ๋‘˜์ค‘ ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ์†์„ฑ๋งŒ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค. ๋‘ ์ธํ„ฐํŽ˜์ด์Šค ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธฐ๋Š” ๊ฐœ๋…๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

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

interface Marketers {
  name: string;
  age: number;
}

function askSomeone(someone: Developers | Marketers) {
  someone.name; // 2๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๋Š” ์†์„ฑ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  someone.skill; // ts(2339) error!
  someone.age; // ts(2339) error!
}

// ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ Developers ํ˜น์€ Marketers ๋‘˜์ค‘ ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ๋งŒ ๋ช…์‹œ
askSomeone({
  name: 'John',
  skill: 'JS', // Developers ์†์„ฑ
});

๋‘ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๋Š” ์†์„ฑ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ž๋™์™„์„ฑ ์—ญ์‹œ ๊ณตํ†ต ์†์„ฑ์ธ name๋งŒ ๋‚˜์˜จ๋‹ค.

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ด€์ ์—์„  askSomeone์„ ํ˜ธ์ถœํ•˜๋Š” ์‹œ์ ์— Developers ํƒ€์ž…์ด ์˜ฌ์ง€, Marketers ํƒ€์ž…์ด ์˜ฌ์ง€ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋Š ํƒ€์ž…์ด ๋“ค์–ด์˜ค๋“  ์˜ค๋ฅ˜๊ฐ€ ์•ˆ๋‚˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ํƒ€์ž…์„ ์ถ”๋ก ํ•œ๋‹ค. ์ฆ‰ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์ด์šฉํ•ด ํƒ€์ž…์˜ ๋ฒ”์œ„๋ฅผ ์ขํžˆ์ง€ ์•Š๋Š” ์ด์ƒ ๊ธฐ๋ณธ์ ์œผ๋กœ Developers๊ณผ Marketers ๋‘ ํƒ€์ž…์ด ๊ณตํ†ต์ ์œผ๋กœ ๊ฐ€์ง€๋Š” name ์†์„ฑ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ.
 

์ธํ„ฐ์„น์…˜ ํƒ€์ž…

๐Ÿ’ก `&` ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•ด ์—ฌ๋Ÿฌ ํƒ€์ž… ์ •์˜๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๋Š” ๋ฐฉ์‹

 

์—ฌ๋Ÿฌ ํƒ€์ž…์„ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋Š” ํ•˜๋‚˜์˜ ํƒ€์ž…์„ ์˜๋ฏธํ•œ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ์—์„œ Developers์™€ Marketers ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž… ์ •์˜๋ฅผ & ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•ด Steve๋ผ๋Š” ํƒ€์ž…์— ํ• ๋‹นํ–ˆ๋‹ค.

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

interface Marketers {
  name: string;
  age: number;
}

type Steve = Developers & Marketers;

 

๊ทธ๋Ÿผ Steve ํƒ€์ž…์€ ์•„๋ž˜์ฒ˜๋Ÿผ ์ •์˜ํ•œ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

{
  name: string;
  skill: string;
  age: number;
}

 

์•„๋ž˜ askSomeone ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ธํ„ฐ์„น์…˜ ํƒ€์ž…์„ ์ด์šฉํ•ด 2๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ช…์‹œํ•˜๋ฉด, ์ด ๋‘ ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ์„ ๋ชจ๋‘ ํฌํ•จํ•˜๋ฏ€๋กœ ๋ชจ๋“  ์†์„ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ์‹œ์—๋„ ๋ชจ๋“  ์†์„ฑ์„ ๋ช…์‹œํ•ด์•ผ ํ•˜๋Š”๋ฐ, 2๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ํ•ฉ์ง‘ํ•ฉ์ด๋ฏ€๋กœ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ ๋„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

function askSomeone(someone: Developers & Marketers) {
  someone.name; // ok
  someone.skill; // ok
  someone.age; // ok
}

// ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ Developers์™€ Marketers ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ์†์„ฑ ๋ช…์‹œ(ํ•ฉ์ง‘ํ•ฉ)
askSomeone({
  name: 'John',
  skill: 'JS',
  age: 30,
});

 

์œ ๋‹ˆ์˜จ ํƒ€์ž…๊ณผ ์ธํ„ฐ์„น์…˜ ๋น„๊ต

๐Ÿ’ก ์‹ค๋ฌด์—์„  ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ๋” ์ž์ฃผ ์“ด๋‹ค

 

์œ ๋‹ˆ์˜จ ํƒ€์ž…
์ธํ„ฐ์„น์…˜ ํƒ€์ž…

 

์ด๋„˜ (Enum)


ํŠน์ • ๊ฐ’๋“ค์˜ ์ง‘ํ•ฉ์„ ์˜๋ฏธํ•˜๋Š” ์ž๋ฃŒํ˜•์œผ๋กœ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  ๋ฌธ์žํ˜•๊ณผ ์ˆซ์žํ˜• ์ด๋„˜์„ ์ง€์›ํ•œ๋‹ค. ์ด๋„˜์€ ๋“œ๋กญ๋‹ค์šด์ด๋‚˜ ์ •ํ•ด์ง„ ๋ชฉ๋ก์˜ ๊ฐ’๋“ค์„ ์ง€์ •ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค. ๋ฌธ์žํ˜•๊ณผ ์ˆซ์žํ˜• ์ด๋„˜์„ ํ˜ผํ•ฉํ•ด์„œ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๊ถŒ๊ณ ํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ตœ๋Œ€ํ•œ ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์ด๋„˜์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.
 

์ˆซ์žํ˜• ์ด๋„˜

์ด๋„˜์—์„œ ๋ณ„๋„ ๊ฐ’์„ ํ• ๋‹นํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋‘ ์ˆซ์žํ˜• ์ด๋„˜์œผ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. ์ด๋„˜์— ๋ชฉ๋ก์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋ก ๊ฐ’์€ 1์”ฉ ์ž๋™ ์ฆ๊ฐ€ํ•œ๋‹ค(0๋ถ€ํ„ฐ ์‹œ์ž‘). ๋งŒ์•ฝ Adidas์— 10์„ ํ• ๋‹นํ•˜๋ฉด Nike๋Š” ์ž๋™์œผ๋กœ 1์ด ์ฆ๊ฐ€ํ•˜์—ฌ 11์ด ๋œ๋‹ค.

enum Shoes {
  Adidas = 10,
  Nike, // 11
}

const myShoes = Shoes.Nike;
console.log(myShoes); // 11

 

TS Playground์—์„œ ์œ„ ์ฝ”๋“œ๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ปดํŒŒ์ผ ํ•ด๋ณด๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋œ๋‹ค. ์™ผ์ชฝ Run ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฝ˜์†”๋กœ๊ทธ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ ์ด๋„˜์€ ๋Ÿฐํƒ€์ž„์‹œ ์‹ค์ œ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์กด์žฌํ•œ๋‹ค. 

 

๐Ÿ’ก enum์˜ ๋‹จ์ 

enum์€ ํŠธ๋žœ์ŠคํŒŒ์ผ๋ง(TS → JS ๋ณ€ํ™˜) ํ›„ IIFE๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋Ÿฐํƒ€์ž„์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ •์  ํƒ€์ž… ์ •๋ณด๊ฐ€ ๋Ÿฐํƒ€์ž„์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ์…ˆ์ด๋‹ค. ๋ฒˆ๋“ค๋Ÿฌ๊ฐ€ IIFE๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋กœ ํŒ๋‹จํ•ด์„œ Tree Shaking(์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ ์‚ญ์ œ)๋„ ์•ˆ๋œ๋‹ค.

 

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

 

๋˜ํ•œ, ๋ฌธ์ž์—ด enum์ด ํ•„์š”ํ•œ ํ•จ์ˆ˜๋‚˜ ๊ฐ์ฒด์— ํ˜ธํ™˜๋˜๋Š” ๊ฐ’(enum๊ณผ ๋™์ผํ•œ ๊ฐ’)์„ ์ „๋‹ฌํ•  ์ˆ˜ ์—†๋Š” ๋‹จ์ ๋„ ์žˆ๋‹ค.

// ์ฝ”๋“œ ์ฐธ๊ณ  - yceffort
enum Direction {
  Up = 'Up',
  Down = 'Down',
  Left = 'Left',
  Right = 'Right',
}

declare function move(direction: Direction): void;

move('Up'); // Error (๋ฌธ์ž์—ด 'Up'์€ Direction.Up๊ณผ ๋™์ผํ•˜์ง€๋งŒ enum์ด ์•„๋‹ˆ์–ด์„œ ์ „๋‹ฌ ๋ถˆ๊ฐ€)
move(Direction.Up); // OK

 

 

๋ฌธ์žํ˜• ์ด๋„˜

๋ฌธ์žํ˜• ์ด๋„˜์€ ์ˆซ์žํ˜• ์ด๋„˜๊ณผ ๋‹ค๋ฅด๊ฒŒ Auto-Incrementing(์ž๋™์ฆ๊ฐ€)์ด ์—†๋‹ค. ๋•Œ๋ฌธ์— ๋ฌธ์žํ˜• ์ด๋„˜์€ ํŠน์ • ๋ฌธ์ž๋‚˜ ๋‹ค๋ฅธ ์ด๋„˜ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}

 

์ด๋„˜ ํ™œ์šฉ

Answer ๋ผ๋Š” ์ด๋„˜ ๋ชฉ๋ก์„ ๋งŒ๋“ค์–ด์„œ, askQuestion ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํƒ€์ž…์„ ์ด๋„˜์œผ๋กœ ์ง€์ •ํ•œ ์˜ˆ์‹œ. ํ•จ์ˆ˜ ํ˜ธ์ถœ์‹œ์—๋„ ํ•ด๋‹น ์ด๋„˜์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

enum Answer {
  Yes = 'Y',
  No = 'N',
}

function askQuestion(answer: Answer) {
  if (answer === Answer.Yes) {
    console.log('์ •๋‹ต์ž…๋‹ˆ๋‹ค');
  }
  if (answer === Answer.No) {
    console.log('์˜ค๋‹ต์ž…๋‹ˆ๋‹ค');
  }
}

askQuestion(Answer.Yes);
askQuestion('Y'); // ts(2345) error!

 

์ด๋„˜ ๋ฐ์ดํ„ฐ(๊ฐ’)์„ ๊ฐ์ฒด์˜ Key๋กœ ์‚ฌ์šฉํ•  ๋• Computed Property { [...]: value }๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

enum SHOE_BRANDS {
  NIKE = 'nike',
  ADIDAS = 'adidas',
  MIZNO = 'mizno',
}

const shoeBrandsKoStrings = {
  [SHOE_BRANDS.NIKE]: '๋‚˜์ดํ‚ค',
  [SHOE_BRANDS.ADIDAS]: '์•„๋””๋‹ค์Šค',
  [SHOE_BRANDS.MIZNO]: '๋ฏธ์ฆˆ๋…ธ',
};

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํด๋ž˜์Šค


ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„  ํด๋ž˜์Šค ์ตœ์ƒ๋‹จ์— ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด์ค˜์•ผํ•˜๋ฉฐ, ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํƒ€์ž…๋„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค. ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์—” public private ๋“ฑ ์œ ํšจ ๋ฒ”์œ„๋„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Persons {
  // ํด๋ž˜์Šค ์ตœ์ƒ๋‹จ์— ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•  ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด์ค˜์•ผํ•จ
  // ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์œ ํšจ ๋ฒ”์œ„๋„ ์„ค์ • ๊ฐ€๋Šฅ(public, private ๋“ฑ)
  private name: string;
  public age: number;

  // ์ƒ์„ฑ์ž์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋„ ํƒ€์ž… ์ง€์ •
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

 

Readonly

ํด๋ž˜์Šค ์†์„ฑ์— readonly ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ ‘๊ทผ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค(ํ• ๋‹น ๋ถˆ๊ฐ€).

class Developers {
  readonly name: string;

  constructor(theName: string) {
    this.name = theName;
  }
}
const john = new Developers('John');
john.name = 'John'; // ts(2540) error! name is readonly.

 

readonly๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์ดˆ๊ธฐ๊ฐ’์„ ์ง€์ •ํ•ด์•ผ ๋œ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— readonly ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

class Developers {
  readonly name: string;
  constructor(readonly name: string) {}
}

 

Accessor

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ์ฒด ํŠน์ • ์†์„ฑ์ด ์ ‘๊ทผ๊ณผ ํ• ๋‹น์— ๋Œ€ํ•ด ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„  ํด๋ž˜์Šค๋กœ ๋งŒ๋“  ๊ฐ์ฒด์—ฌ์•ผ ํ•œ๋‹ค.

class Developer {
  name: string;
}

const josh = new Developer();
josh.name = 'Josh Bolton';

 

๋งŒ์•ฝ name ์†์„ฑ์— ์ œ์•ฝ ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ get๊ณผ set์„ ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค. get๋งŒ ์„ ์–ธํ•˜๊ณ  set์„ ์„ ์–ธํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—” ์ž๋™์œผ๋กœ readonly๋กœ ์ธ์‹๋œ๋‹ค.

class Developer {
  private name: string;

  get name(): string {
    return this.name;
  }

  // name์ด 5๊ธ€์ž๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์—๋Ÿฌ ์ถœ๋ ฅ
  set name(newValue: string) {
    if (newValue && newValue.length > 5) {
      throw new Error('์ด๋ฆ„์ด ๋„ˆ๋ฌด ๊น๋‹ˆ๋‹ค');
    }
    this.name = newValue;
  }
}

const josh = new Developer();

josh.name = 'Josh Bolton'; // Error
josh.name = 'Josh';

 

Abstract Class (์ถ”์ƒ ํด๋ž˜์Šค)

์ถ”์ƒ ํด๋ž˜์Šค๋Š” ํŠน์ • ํด๋ž˜์Šค์˜ ์ƒ์† ๋Œ€์ƒ์ด ๋˜๋Š” ํด๋ž˜์Šค๋‹ค. ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ ์†์„ฑ, ๋ฉ”์„œ๋“œ์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•œ๋‹ค.

abstract class Developer {
  abstract coding(): void; // 'abstract'๊ฐ€ ๋ถ™์œผ๋ฉด ์ƒ์† ๋ฐ›์€ ํด๋ž˜์Šค์—์„œ ๋ฌด์กฐ๊ฑด ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
  drink(): void {
    console.log('drink sth');
  }
}

class FrontEndDeveloper extends Developer {
  coding(): void {
    // Developer ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์€ ํด๋ž˜์Šค์—์„œ ๋ฌด์กฐ๊ฑด ์ •์˜ํ•ด์•ผ ํ•˜๋Š” ๋ฉ”์„œ๋“œ
    console.log('develop web');
  }
  design(): void {
    console.log('design web');
  }
}

const dev = new Developer(); // error: cannot create an instance of an abstract class
const josh = new FrontEndDeveloper();

josh.coding(); // develop web
josh.drink(); // drink sth
josh.design(); // design web

 


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