2.Typescript

REPL(Read-Eval-Print-Loop)

ํ„ฐ๋ฏธ๋„์—์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ REPL์„ ์“ฐ๊ณ  ์‹ถ์œผ๋ฉด ts-node๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

npx ts-node

Interface vs Type

Interface์™€ Type Alias ๋‹ค์†Œ ๋น„์Šทํ•ด๋ณด์ด๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค์ด๋‚˜ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…์ด ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์„ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์ค‘ ํ•˜๋‚˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์„ ์–ธ์„ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

์•„๋ž˜์˜ ํƒ€์ž…๋“ค์€ ๋‚ด๊ฐ€ ํ˜„์žฌ ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ๋ชจ์…˜ ํƒ€์ž…๋“ค ์ค‘ ์ผ๋ถ€๋ถ„์„ ๊ฐ€์ ธ์™”๋‹ค.

Interface

์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ช…์‹œ์ ์œผ๋กœ ํ™•์žฅ์„ ์‚ฌ์šฉํ•ด์„œ ์ •์˜๋ฅผ ํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.

export interface PromotionCoupon {
  promoId: string,
  name: string,
  issuanceType: PromotionIssuance,
  createdAt: string,
  expiryAt: string,
  code: string,
  discountType: PromotionDiscount,
  discountRate: number,
}

export interface PromotionCouponList extends PromotionCoupon {
  targetCount: number,
  issuanceCount: number,
}

๋˜ Type Alias์—์„œ ํ•˜์ง€ ๋ชปํ•˜๋Š” ์„ ์–ธ ๋ณ‘ํ•ฉ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

interface ButtonInterface {
  onInit():void;
  onClick():void;
}

...

interface ButtonInterface {
  onToggle():void;
}

์œ„์™€ ๊ฐ™์ด ์„ ์–ธ ๋˜์—ˆ์„ ๋•Œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์ง€ ์•Š๋Š”๋‹ค.

Type

ํƒ€์ž…์€ ๋ณ‘ํ•ฉํ•˜๊ณ ์ž ํ•˜๋Š” ํƒ€์ž…๊ณผ & ๊ธฐํ˜ธ๋ฅผ ํ™œ์šฉํ•ด์„œ ํƒ€์ž… ๋ณ‘ํ•ฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

export type PromotionOwnerList = {
  uuid: string,
  email: string,
  nickname: string,
  userPromoStatusId: string,
  promoId: string,
  maxUseAt: string,
  usedAt: string | null,
  isUsed: boolean,
  createdAt: string,
  isChecked?: boolean,
}

export type PromotionCandidateList = User & {
  provider: Provider,
  emailCert: boolean,
  privacyAgree: boolean,
  eventAgree: boolean,
  createdAt: string,
  isChecked?: boolean,
}
type ButtonType = {
  onInit():void;
  onClick():void;
}

// [์˜ค๋ฅ˜]
// 'ButtonType' ์‹๋ณ„์ž๊ฐ€ ์ค‘๋ณต๋˜์—ˆ๋‹ค.
type ButtonType = {
  onToggle():void;
}

ํƒ€์ž…์—์„œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ํƒ€์ž… ์ถ”๋ก ๊ณผ ํƒ€์ž… ๋‹จ์–ธ

ํƒ€์ž… ์ถ”๋ก 

let x = 3;

let y = 'hello';

์œ„์™€ ๊ฐ™์ด x์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š๋”๋ผ๋„ numberํƒ€์ž…์œผ๋กœ y์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š๋”๋ผ๋„ stringํƒ€์ž…์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค.

ํƒ€์ž… ๋‹จ์–ธ

let assertion:any = "ํƒ€์ž… ์–ด์„ค์…˜์€ 'ํƒ€์ž…์„ ๋‹จ์–ธ'ํ•œ๋‹ค.";

// ๋ฐฉ๋ฒ• 1: assertion ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ string์œผ๋กœ ๋‹จ์–ธ ์ฒ˜๋ฆฌ
let assertion_count:number = (<string>assertion).length;
let assertion:any = "ํƒ€์ž… ์–ด์„ค์…˜์€ 'ํƒ€์ž…์„ ๋‹จ์–ธ'ํ•œ๋‹ค.";

// ๋ฐฉ๋ฒ• 2: assertion ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ string์œผ๋กœ ๋‹จ์–ธ ์ฒ˜๋ฆฌ
let assertion_count:number = (assertion as string).length;

๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๋‹ค. ํ•˜์ง€๋งŒ JSX์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” as ๋ฌธ๋ฒ•๋งŒ ํ—ˆ์šฉ๋œ๋‹ค.

๋ณดํ†ต JSX์—์„œ ๋งŽ์ด ์“ฐ๋Š” ํƒ€์ž… ๋‹จ์–ธ์—๋Š” divํƒœ๊ทธ์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์ƒํƒœ์—์„œ ํ•ด๋‹น div์•ˆ์˜ input์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์— ํƒ€์ž… ๋‹จ์–ธ์„ ๋งŽ์ด ์‚ฌ์šฉํ–ˆ๋‹ค.

  const onChangeCategory = useCallback((e: React.FormEvent<HTMLDivElement>) => {
    const { value } = (e.target as HTMLInputElement);
    ...
  }, []);

Union Type vs Intersection Type

Union Type

์œ ๋‹ˆ์˜จ ํƒ€์ž…(Union Type)์€ A์ด๊ฑฐ๋‚˜ B์ด๋‹ค ๋ผ๋Š” ์˜๋ฏธ์˜ ํƒ€์ž…์ด๋‹ค.

๋ณดํ†ต ์ง€์ •๋œ ๊ฐ’ ์ด์™ธ์˜ ๊ฐ’์ด ๋“ค์–ด๊ฐ€์ง€ ์•Š์•„์•ผ ํ•  ๋•Œ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ์ง€์ •ํ•ด์„œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด๋‹ค.

export type PromotionCategory = 'COUPON' | 'LINK';
export type PromotionDiscount = 'FREE' | 'DISCOUNT';

Intersection Type

์ธํ„ฐ์„น์…˜ ํƒ€์ž…(Intersection Type)์€ ์—ฌ๋Ÿฌ ํƒ€์ž…์„ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋Š” ํ•˜๋‚˜์˜ ํƒ€์ž…์ด๋‹ค.

export type PromotionCandidateList = User & {
  provider: Provider,
  emailCert: boolean,
  privacyAgree: boolean,
  eventAgree: boolean,
  createdAt: string,
  isChecked?: boolean,
}
interface Person {
  name: string;
  age: number;
}
interface Developer {
  name: string;
  skill: number;
}
type Capt = Person & Developer;

Optional Parameter

JavaScript์—์„œ๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜์˜€์„ ๋•Œ, ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  undefined ๊ฐ’์„ ์–ป๊ฒŒ ๋œ๋‹ค.

export type PromotionCandidateList = User & {
  provider: Provider,
  emailCert: boolean,
  privacyAgree: boolean,
  eventAgree: boolean,
  createdAt: string,
  isChecked?: boolean, <- option
}
function printName(obj: { first: string; last?: string }) {
  // ...
}
// ๋‘˜ ๋‹ค OK
printName({ first: "Bob" });
printName({ first: "Alice", last: "Alisson" });

References

Last updated