2. TypeScript

  • REPL

  • TypeScript

    • Interface vs Type

    • νƒ€μž… μΆ”λ‘ 

    • Union Type vs Intersection Type

    • Optional Parameter

κ°•μ˜ 정리

TypeScript

νƒ€μž…μŠ€ν¬λ¦½νŠΈ κ³΅μ‹λ¬Έμ„œ

κ°„λ‹¨νžˆ REPL을 μ“°κ³  μ‹Άλ‹€λ©΄ ts-nodeλ₯Ό μ‹€ν–‰ (TS Playground도 μ’‹λ‹€)

  • npx ts-node

νƒ€μž… μ§€μ •

νƒ€μž…μ„ μž‘μ•„μ£Όλ©΄ νƒ€μž…μ— μ •ν™•νžˆ λ§žλŠ” κ²ƒλ§Œ ν• λ‹Ήν•  수 μžˆλ‹€.

let name: string;
let age: number;

name = '홍길동';
age = 13;

name = 13; // error TS2322: Type 'number' is not assignable to type 'string'.
age = '홍길동'; // error TS2322: Type 'string' is not assignable to type 'number'.

let human: {
  name: string;
  age: number;
};

human = { name: '홍길동', age: 13 };
type Human = {
  name: string;
  age: number;
};

let boy: Human;

boy = { name: '홍길동', age: 13 };

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

let girl: Person;

girl = { name: '홍길동', age: 13 };

function add(x: number, y: number): number {
  return x + y;
}

add(1, 2);

add('Hello', 'World'); // TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

function sub(x: number, y: number): string {
  return x - y; // TS2322: Type 'number' is not assignable to type 'string'.
}

λ¦¬ν„°λŸ΄ νƒ€μž…, Unionμ—μ„œ μœ μš©ν•˜κ²Œ 쓰인닀.

let category: 'food';

category = 'food';

λ°°μ—΄ νƒ€μž…

let numbers: number[];
let counts: Array<number>;

numbers = [1, 2, 3];

νŠœν”Œ νƒ€μž…

let anythings: any[];

anythings = ['hp', 256];

let pair: [string, number];

pair = ['hp', 256];

νƒ€μž… μΆ”λ‘ , TSμ—μ„œλŠ” νƒ€μž… 좔둠을 ꢌμž₯ν•œλ‹€.

const name: string = '홍길동';

const name = '홍길동';

Union Type

  • μ—¬λŸ¬ νƒ€μž… 쀑 ν•˜λ‚˜μ΄λ‹€.

  • boolean은 true | false와 κ°™λ‹€.

type bool = true | false;

let flag: bool;

flag = true;

flag = false;

flag = 3; // TS2322: Type 'number' is not assignable to type 'bool'.
  • 맀개 λ³€μˆ˜λ₯Ό μ œν•œν•˜κ±°λ‚˜ ν•  λ•Œ 맀우 μœ μš©ν•˜κ²Œ μ“Έ 수 μžˆλ‹€.

  • Union으둜 νƒ€μž…μ„ μž‘μ•„μ£Όλ©΄ μžλ™ 완성이 맀우 κ°•λ ₯ν•˜λ‹€.

type Category = 'food' | 'toy' | 'bag';

function fetchProducts({ category }: { category: Category }) {
  console.log(`Fetch ${category}`);
}
  • λ ˆκ±°μ‹œ μ½”λ“œ ν™˜κ²½μ˜ 경우 계속 λ³€ν™”κ°€ 생기기 λ•Œλ¬Έμ— Union을 μ•ˆ μ“Έ μˆ˜κ°€ μ—†λ‹€.

  • ReactNodeκ°€ λŒ€ν‘œμ μ΄λ‹€.

let target: string | number;

target = '홍길동';

target = 13;

target = null; // TS2322: Type 'null' is not assignable to type 'string | number'.

target = undefined; // TS2322: Type 'undefined' is not assignable to type 'string | number'.

let targetName: string | undefined;

targetName = '홍길동';

targetName = undefined;
  • undefinedλ₯Ό 직접 μ“Έ 일은 μ—†κ³  ν•¨μˆ˜ λ§€κ°œλ³€μˆ˜μ—μ„œ optional ν•˜κ²Œ λ°›κ³  싢은 κ²½μš°μ— μ‚¬μš©λ  수 μžˆλ‹€.

  • ν•˜μ§€λ§Œ 이런 κ²½μš°μ—λ„ ? 기호λ₯Ό μ΄μš©ν•˜μ—¬ optional parameter둜 μ²˜λ¦¬ν•˜λ©΄ undefined도 같이 받을 수 μžˆλ‹€.

function greeting(name?: string): string {
  return `Hello, ${name || 'world'}`;
}
  • κΈ°λ³Έκ°’(default parameter)을 μž‘μ•„μ£Όλ©΄ μ’‹λ‹€.

function greeting(name: string = 'world'): string {
  return `Hello, ${name}`;
}
  • λ§€κ°œλ³€μˆ˜(parameter)κ°€ 객체(object)일 λ•Œλ„ ν™œμš©ν•  수 μžˆλ‹€.

function greeting({ name, age }: { name: string; age?: number }): string {
  return age ? `${name} (${age})` : name;
}
  • νƒ€μž…μ„ μž‘μ•„μ€€ 방식

type Human = {
  name: string;
  age?: number;
};

function greeting({ name, age }: Human): string {
  return age ? `${name} (${age})` : name;
}

greeting(); // TS2554: Expected 1 arguments, but got 0.

greeting({ name: '홍길동' });

greeting({ name: '홍길동', age: 13 });

Intersection Type

  • νƒ€μž…μ„ ν™•μž₯ν•˜λŠ” κ°„λ‹¨ν•œ 방식

  • type Person은 Humanκ³Ό Creature을 λͺ¨λ‘ λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

type Human = {
  name: string;
  age: number;
};

type Creature = {
  hp: number;
  mp: number;
};

type Person = Human & Creature;

let person: Person;

person = { name: '홍길동', age: 13, hp: 256, mp: 16 };

Generics, Utility Types, and Tips

μœ ν‹Έλ¦¬ν‹° νƒ€μž…

νŽΈμ§‘κΈ° μžλ™ μ™„μ„± + 개발 ν™˜κ²½μ—μ„œμ˜ 였λ₯˜ 검사

  • TypeScriptλ₯Ό μ‚¬μš©ν•˜λŠ” 핡심적인 이유

  • 였래된 라이브러리의 κ²½μš°μ— d.ts 파일둜 νƒ€μž… 지원, νŒ¨ν‚€μ§€ 이름은 @types/~ ν˜•νƒœ

  • DefinitelyTyped


ν•Έλ“œλΆ μ •λ…ν•˜κΈ° The Basics μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ λͺ¨λ“  값은 값에 λ”°λΌμ„œ μ‹€ν–‰ν•  수 μžˆλŠ” μ—°μ‚°μžμ˜ 집합이 μžˆλ‹€.

message.toLowerCase();

message();

첫 번째 μ½”λ“œλŠ” toLowerCaseλΌλŠ” property에 μ ‘κ·Όν•œ 후에 그것을 ν˜ΈμΆœν•˜μ˜€λ‹€. 두 번째 μ½”λ“œλŠ” messageλ₯Ό μ§μ ‘μ μœΌλ‘œ ν˜ΈμΆœν•˜μ˜€λ‹€.

κ·ΈλŸ¬λ‚˜ μš°λ¦¬κ°€ messageλΌλŠ” 값을 λͺ¨λ₯Έλ‹€κ³  κ°€μ •ν•˜λ©΄ (μ‹€μ œλ‘œλ„ κ½€ ν”ν•˜λ‹€) μš°λ¦¬λŠ” μ½”λ“œλ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œ μ–΄λ–€ 결과값을 얻을 수 μžˆμ„μ§€ ν™•μ‹€ν•˜κ²Œ 말할 수 μ—†λ‹€. 각 μ—°μ‚°μžμ˜ ν–‰μœ„λŠ” 값이 무엇이냐에 λ‹¬λ €μžˆλ‹€.

  • messageλŠ” ν˜ΈμΆœν•  수 μžˆλŠ”κ°€?

  • toLowerCaseλΌλŠ” 프라퍼티λ₯Ό κ°–κ³  μžˆλŠ”κ°€?

  • λ§Œμ•½ κ·Έλ ‡λ‹€λ©΄, toLowerCaseλŠ” ν˜ΈμΆœν•  수 μžˆλŠ”κ°€?

  • λ§Œμ•½ 두 값이 ν˜ΈμΆœν•  수 μžˆλ‹€λ©΄, 무엇을 리턴할 것인가?

이 μ§ˆλ¬Έμ— λŒ€ν•œ 닡은 일반적으둜 μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œ μš°λ¦¬κ°€ λ¨Έλ¦¬μ†μœΌλ‘œ μƒκ°ν•˜κ³  μ‹€μ œλ‘œ μΌμΉ˜ν•˜κΈ°λ₯Ό λ°”λž€λ‹€.

messageκ°€ μ•„λž˜μ™€ 같이 μ •μ˜λ˜μ—ˆλ‹€κ³  ν•΄λ³΄μž.

const message = 'Hello World!';

μΆ”μΈ‘ν–ˆκ² μ§€λ§Œ, λ§Œμ•½ message.toLowerCase()λ₯Ό μ‹€ν–‰ν•œλ‹€λ©΄ μš°λ¦¬λŠ” μ†Œλ¬Έμžλ‘œ λ³€ν™˜λœ λ˜‘κ°™μ€ λ¬Έμžμ—΄μ„ 얻을 수 μžˆλ‹€.

2번째 μ€„μ˜ μ½”λ“œλŠ” μ–΄λ–€κ°€? λ§Œμ•½ μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ μΉœμˆ™ν•˜λ‹€λ©΄ μ—λŸ¬μ™€ ν•¨κ»˜ μ‹€νŒ¨ν•  κ²ƒμ΄λΌλŠ”κ²ƒμ„ μ•Œ 것이닀.

TypeError: message is not a function

μ΄λŸ¬ν•œ μ—λŸ¬λ₯Ό ν”Όν•  수 μžˆλ‹€λ©΄ 쒋을 것이닀.

μš°λ¦¬κ°€ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  λ•Œ, μžλ°”μŠ€ν¬λ¦½νŠΈ λŸ°νƒ€μž„μ΄ 무엇을 ν•  μ§€ μ„ νƒν•˜λŠ” 방법은 κ°’μ˜ νƒ€μž…μ„ μ΄ν•΄ν•˜λŠ” 것이닀, μ–΄λ–€ μ’…λ₯˜μ˜ μ—°μ‚°μžμ™€λ₯Ό κ°–κ³  μžˆλŠ”μ§€. 이것은 TypeErrorκ°€ string인 Hello World!λŠ” ν•¨μˆ˜λ‘œ μ‹€ν–‰ν•  수 μ—†λ‹€λŠ” 것을 μ•”μ‹œν•΄μ£ΌλŠ” 뢀뢄이닀.

λͺ‡λͺ‡ 값듀은, stringκ³Ό number와 같은 값듀은 λŸ°νƒ€μž„μ— typeof μ—°μ‚°μžλ₯Ό μ΄μš©ν•˜μ—¬ νƒ€μž…μ„ 식별할 수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ ν•¨μˆ˜μ™€ 같은 λ‹€λ₯Έ 값듀은 λŸ°νƒ€μž„μ— νƒ€μž…μ„ 식별할 수 μžˆλŠ” 방법이 μ—†λ‹€. 예λ₯Ό λ“€λ©΄ μ•„λž˜ ν•¨μˆ˜λ₯Ό μƒκ°ν•΄λ³΄μž.

function fn(x) {
  return x.flip();
}

μš°λ¦¬λŠ” 이 μ½”λ“œλ₯΄ μ½μœΌλ©΄μ„œ ν˜ΈμΆœν•  수 μžˆλŠ” flib 프라퍼티λ₯Ό κ°€μ§„ 객체λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 전달해야 이 ν•¨μˆ˜κ°€ 싀행될 κ²ƒμ΄λΌλŠ” 것을 μ•Œ 수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ½”λ“œκ°€ 싀행될 λ•Œ 이런 정보λ₯Ό νŒλ‹¨ν•  수 μžˆλŠ” 방법이 μ—†λ‹€. 순수 μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ fn이 νŠΉμ • κ°’μœΌλ‘œ 무엇을 ν•  μ§€ μ•Œ 수 μžˆλŠ” 방법은 ν˜ΈμΆœν•˜κ³  무엇이 μΌμ–΄λ‚˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것이닀. μ΄λŸ¬ν•œ 방식은 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° 전에 μ½”λ“œκ°€ μ–΄λ–€ 행동을 ν•  것인지 μ˜ˆμΈ‘ν•˜κΈ° μ–΄λ ΅κ²Œ ν•œλ‹€, 즉 μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œ μž‘μ„±ν•˜λŠ” μ½”λ“œκ°€ μ–΄λ–€ 일을 ν• μ§€ μ•ŒκΈ° μ–΄λ ΅κ²Œ λ§Œλ“ λ‹€.

이런 λ°©μ‹μ—μ„œ λ³Έ 것 처럼, νƒ€μž…μ€ μ–΄λ–€ 값이 fn에 전달될 수 있고, μ–΄λ–€ 값은 μ—λŸ¬κ°€ λ°œμƒν•  것인지λ₯Ό λ¬˜μ‚¬ν•˜λŠ” 방식이닀. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ½”λ“œλ₯Ό μ‹€ν–‰ν•΄μ•Όλ§Œ κ²°κ³Όλ₯Ό μ•Œ 수 μžˆλŠ” 동적 타이핑을 μ œκ³΅ν•œλ‹€.

이에 λŒ€ν•œ λŒ€μ•ˆμ€ 정적 νƒ€μž… μ‹œμŠ€ν…œμ„ μ‚¬μš©ν•˜λŠ” 것이닀. μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° 전에 μ½”λ“œκ°€ μ–΄λ–»κ²Œ 싀행될 것인지λ₯Ό μ˜ˆμΈ‘ν•  수 μžˆλ‹€.

Static type-checking

Everyday Types Narrowing More on Functions Object Types Type Manipulation Classes Modules

Last updated