๐Ÿ“Œ TypeScript์™€ JavaScript ๊ด€๊ณ„

๋ชจ๋“  JavaScript๋Š” TypeScript์ด์ง€๋งŒ, ๋ชจ๋“  TypeScript๊ฐ€ JavaScript๋Š” ์•„๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
interface State {
name: string;
capital: string;
}
const states: State[] = [
{ name: "yiju", capital: "๊ฒฝ๊ธฐ๋„" },
{ name: "kim", capitol: "์„œ์šธ" },
]; // Error
// Type '{ name: string; capitol: string; }' is not assignable to type 'State'.
// Object literal may only specify known properties, but 'capitol' does not exist in type 'State'. Did you mean to write 'capital'?

์œ„ ์˜ˆ์‹œ๋ฅผ ์„ค๋ช…ํ•˜๋ฉด, ์•ž์„œ ๋งํ•œ ๋ชจ๋“  ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋‹ค ๋ผ๊ณ  ํ•˜๋Š” ๋ง์€ ํ‹€๋ ธ๋‹ค.

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

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋žจ $\supset$ ( ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋žจ $\cap$ ํƒ€์ž…์ฒด์ปค๋ฅผ ํ†ต๊ณผํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ )

๐Ÿ“Œ ์ฝ”๋“œ ์ƒ์„ฑ๊ณผ ํƒ€์ž…์€ ๊ด€๋ จ์ด ์—†๋‹ค.

TypeScript๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ ๊ณผ์ •์„ ํ†ตํ•ด JavaScript๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

์ด ๋•Œ, ํƒ€์ž… ์ฝ”๋“œ๋“ค์€ ์‚ฌ๋ผ์ง€๊ฒŒ๋œ๋‹ค.

1
2
3
4
5
6
// TypeScript
interface State {
name: string;
capital: string;
}
const states: State[] = [{ name: "yiju", capital: "๊ฒฝ๊ธฐ๋„" }];

์œ„ ์ฝ”๋“œ๋ฅผ JavaScript๋กœ ์ปดํŒŒ์ผํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋งŒ ๋‚จ๋Š”๋‹ค.

1
2
3
// JavaScript
"use strict";
const states = [{ name: "yiju", capital: "๊ฒฝ๊ธฐ๋„" }];

์ปดํŒŒ์ผ ์ดํ›„ ๋Ÿฐํƒ€์ž„ ์‹œ์ ์— JavaScript ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

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

๐Ÿ“Œ any ํƒ€์ž… ์ง€์–‘ํ•˜๊ธฐ

  • any ํƒ€์ž…์€ ์•ˆ์ „์„ฑ์ด ์—†๋‹ค.
  • ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜(contract: ๊ณ„์•ฝ)์„ ๋ฌด์‹œํ•œ๋‹ค.
1
2
3
4
5
function calcAge(birthDate: Date): number {
//...
}
let birthDate: any = "1995-12-04";
calcAge(birthDate); // ์ •์ƒ
  • ์–ธ์–ด ์„œ๋น„์Šค๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.(์ž๋™์™„์„ฑ ๋ฐ ๋„์›€๋ง)
  • ์ฝ”๋“œ ์„ค๊ณ„๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ค๊ณ  ์‹ ๋ขฐ๋„๋ฅผ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค.

โญ๏ธโญ๏ธโญ๏ธโญ๏ธโญ๏ธ ํƒ€์ž…์€ ๊ฐ’๋“ค์˜ ์ง‘ํ•ฉ์ด๋‹ค.

ํƒ€์ž…์€ ๊ฐ’๋“ค์˜ ์ง‘ํ•ฉ์ด๋‹ค. ๋˜ํ•œ ์ด ์ง‘ํ•ฉ์€ ํƒ€์ž…์˜ ๋ฒ”์œ„๋ผ๊ณ  ๋งํ•œ๋‹ค. ์ด ๊ฐœ๋…์„ ์•Œ์•„๋‘ฌ์•ผ ํƒ€์ž…์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ธฐ ์šฉ์ดํ•˜๋‹ค.

TypeScript๋Š” ํƒ€์ž…์„ ๊ฒ€์‚ฌํ•  ๋•Œ, ์„ ์–ธ๋œ ํƒ€์ž…์— ํ• ๋‹น ๊ฐ€๋Šฅํ•œ ์ง€(assignable)๋ฅผ ํŒ๋‹จํ•œ๋‹ค.

1
2
3
type AB = "A" | "B";

const c: AB = "C"; // Error: Type '"C"' is not "assignable" to type 'AB'.
  • โ€œCโ€ ํ˜•์‹์€ AB ํ˜•์‹์— ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • โ€œCโ€ ํ˜•์‹์€ AB ํ˜•์‹์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด ์•„๋‹ˆ๋‹ค.
  • โ€œCโ€ ํ˜•์‹์€ AB ํ˜•์‹์˜ ์›์†Œ๊ฐ€ ์•„๋‹ˆ๋‹ค.
  • โ€œCโ€ ํ˜•์‹์€ AB ํ˜•์‹์˜ ์„œ๋ธŒํƒ€์ž…์ด ์•„๋‹ˆ๋‹ค.
  • โ€œCโ€ ํ˜•์‹์€ AB ํ˜•์‹์˜ ์ƒ์† ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.

๋ชจ๋‘ ๊ฐ™์€ ๋ง์ด๋ฏ€๋กœ ์—ผ๋‘ํ•˜์ž.

๐Ÿ•น & ์—ฐ์‚ฐ์ž (๊ต์ง‘ํ•ฉ, intersection)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Person {
name: string;
}
interface Lifespan {
birth: Date;
death?: Date;
}
type PersonSpan = Person & Lifespan;

const ps: PersonSpan = {
name: "yiju",
birth: new Date("1995/12/04"),
death: new Date("2100/10/10"),
}; // ์ •์ƒ
  • & ์—ฐ์‚ฐ์ž๋Š” ๋‘ ํƒ€์ž…์˜ ์ธํ„ฐ์„น์…˜(๊ต์ง‘ํ•ฉ)์„ ๊ณ„์‚ฐํ•œ๋‹ค.

์–ธ๋œป ๋ณด๋ฉด ๊ต์ง‘ํ•ฉ์ด๋ผํ•˜๋ฉด ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์š”์†Œ๋งŒ ํ™•์ธํ•œ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์–ด ์œ„ ์˜ˆ์‹œ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ ๋‹ค.

ํ•˜์ง€๋งŒ, ํƒ€์ž… ์—ฐ์‚ฐ์ž๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์†์„ฑ์ด ์•„๋‹Œ ํƒ€์ž…์˜ ๋ฒ”์œ„(๊ฐ’์˜ ์ง‘ํ•ฉ)์— ์ ์šฉ๋œ๋‹ค. ํ•ด๋‹น ํƒ€์ž…๊ณผ ๋”๋ถˆ์–ด ์ถ”๊ฐ€์ ์ธ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ๊ฐ’๋„ PersonSpan ํƒ€์ž…์— ์†ํ•œ๋‹ค.

์ฆ‰, PersonSpan์€ Person ์ด๋ผ๋Š” ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” ์ง‘ํ•ฉ๊ณผ Lifespan ์ด๋ผ๋Š” ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” ์ง‘ํ•ฉ์˜ ๊ต์ง‘ํ•ฉ์ด ๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Person์˜ name ํ”„๋กœํผํ‹ฐ๋„ ๊ฐ€์ ธ์•ผ ํ•˜๊ณ  Lifespan์˜ birth ์†์„ฑ์„ ๊ฐ€์ง„ ์ง‘ํ•ฉ์„ ์˜๋ฏธํ•œ๋‹ค. (deate ์†์„ฑ์€ optionalํ•˜๋ฏ€๋กœโ€ฆ)

ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉดโ€ฆ extends ๊ตฌ๋ฌธ์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
interface Person {
name: string;
}
interface PersonSpan extends Person {
birth: Date;
death?: Date;
}

์œ ๋‹ˆ์˜จ์—์„œ & ์—ฐ์‚ฐ์ž

1
type K = keyof (Person | Lifespan); // type is 'never'

keyof ์—ฐ์‚ฐ์ž๋Š” ๊ฐ์ฒด์˜ ํ‚ค ๊ฐ’๋“ค์„ ์ˆซ์ž๋‚˜ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด ์œ ๋‹ˆ์–ธ์„ ์ƒ์„ฑํ•œ๋‹ค.

์ฆ‰, Person์˜ key๊ฐ’ name, Lifespan์˜ key๊ฐ’ birth,death์˜ ์œ ๋‹ˆ์˜จ์ธ name | birth ์— ์†ํ•˜๋Š” ๊ฐ’์€ ์–ด๋– ํ•œ ํ‚ค๋„ ์—†๊ธฐ ๋•Œ๋ฌธ์— never๊ฐ€ ๋œ๋‹ค.

๋ช…ํ™•ํžˆ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค

1
2
keyof (A&B) = (keyof A) | (keyof B); // A์˜ key ๊ฐ’์ด๊ฑฐ๋‚˜ B์˜ key ๊ฐ’์ธ ๊ฒƒ
keyof (A|B) = (keyof A) & (keyof B); // A์˜ key ๊ฐ’์ด๋ฉด์„œ B์˜ key ๊ฐ’์ธ ๊ฒƒ

โœˆ๏ธ ์ œ๋„ค๋ฆญ ์ƒ์†

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface Point {
x: number;
y: number;
}
type PointKeys = keyof Point; // type is "x" | "y"

function sortBy<K extends keyof T, T>(vals: T[], key: K): T[] {
// ...
}

const pts: Point[] = [
{ x: 1, y: 1 },
{ x: 2, y: 0 },
];
sortBy(pts, "x"); // ์ •์ƒ 'x'๋Š” 'x'|'y'๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค.
sortBy(pts, "y"); // ์ •์ƒ 'y'๋Š” 'x'|'y'๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค.
sortBy(pts, "z"); // Error: Argument of type '"z"' is not assignable to parameter of type 'keyof Point'.
  • type K๋Š” type T์˜ ์ƒ์†์„ ๋ฐ›๋Š”๋‹ค.
  • ์œ„ ํ•จ์ˆ˜์—์„œ T๊ฐ€ ๊ณง Point ์ด๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ K๋Š” keyof T์ด๋ฏ€๋กœ โ€˜xโ€™|โ€™yโ€™ ์ด๋‹ค.
  • K extends keyof T๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œํ•œ๋œ ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

๐Ÿฆ– ํƒ€์ž… ๊ณต๊ฐ„๊ณผ ๊ฐ’ ๊ณต๊ฐ„ ๊ตฌ๋ถ„ํ•˜๊ธฐ

JavaScript์˜ symbol์€ ํƒ€์ž… ๊ณต๊ฐ„์ด๋‚˜ ๊ฐ’ ๊ณต๊ฐ„ ์ค‘ ํ•œ ๊ณณ์— ์กด์žฌํ•œ๋‹ค. symbol์€ ์ด๋ฆ„์ด ๊ฐ™๋”๋ผ๋„ ์†ํ•˜๋Š” ๊ณต๊ฐ„์— ๋”ฐ๋ผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ๋‹ค๋ฅด๋‹ค.

1
2
3
4
5
type T1 = "string literal";
type T2 = 123;

const v1 = "string literal";
const v2 = 123;
  • type ๋’ค์˜ ์‹ฌ๋ณผ์ธ T1, T2๋Š” ํƒ€์ž… ๊ณต๊ฐ„์— ์žˆ์œผ๋ฏ€๋กœ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ ์‚ฌ๋ผ์ง„๋‹ค.

class์™€ enum์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ’, ํƒ€์ž… ๋‘๊ฐ€์ง€ ๋ชจ๋‘ ๊ฐ€๋Šฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Cylinder {
radius = 1;
height = 1;
}

function calcVolume(shape: unknown) {
if (shape instanceof Cylinder) {
shape; // ์ •์ƒ, ํƒ€์ž…์€ Cylinder
shape.radius; // ์ •์ƒ, ํƒ€์ž…์€ number
}
}

const v = typeof Cylinder; // ๊ฐ’์ด 'function'
type T = typeof Cylinder; // ํƒ€์ž…์ด typeof Cylinder
  • ํด๋ž˜์Šค๊ฐ€ ๊ฐ’์œผ๋กœ ์“ฐ์ผ ๋•Œ๋Š” ์ƒ์„ฑ์ž๊ฐ€ ์‚ฌ์šฉ๋˜์ง€๋งŒ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉ๋  ๋•Œ๋Š” ์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ Cylinder๊ฐ€ ์ธ์Šคํ„ด์Šค์˜ ํƒ€์ž…์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด๋‹ค.