Typescript: More On Functions

@choi2021 ยท October 23, 2023 ยท 13 min read

More On Functions๐Ÿ˜ƒ

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฒ•์„ ์•Œ์•„๋ณด์ž

Function Type Expressions

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ fuction์„ ํ‘œํ˜„ํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ parameter์™€ return ๊ฐ’์— ๋Œ€ํ•ด ํƒ€์ž…์œผ๋กœ ํ‘œํ˜„ํ•œ๋‹ค. Parameter type์˜ ๊ฒฝ์šฐ ํƒ€์ž…์„ ์ •ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด any๋กœ ์ •ํ•ด์ง„๋‹ค.

function greeter(fn: (a: string) => void) {
  fn("Hello, World")
}

function printToConsole(s: string) {
  console.log(s)
}

greeter(printToConsole)

Call Signatures

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜๋Š” ๊ฐ์ฒด๋‹ค. ์ด์ ์ด ์ค‘์š”ํ•œ ์ ์€ ํ•จ์ˆ˜๊ฐ€ ์†์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, function type annotation์—์„œ๋Š” ์†์„ฑ์„ ํ• ๋‹นํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•œ๋‹ค. ์†์„ฑ์„ ํ• ๋‹นํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•ด๋‹น ์†์„ฑ์— ๋Œ€ํ•œ call signature๋ฅผ ํ• ๋‹นํ•ด์•ผ ํ•œ๋‹ค.

type DescribableFunction = {
  description: string
  (someArg: number): boolean
}
function doSomething(fn: DescribableFunction) {
  console.log(fn.description + " returned " + fn(6))
}

function myFunc(someArg: number) {
  return someArg > 3
}
myFunc.description = "default description"

doSomething(myFunc)

Construct Signatures

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜ ์„ ์–ธ๋ฌธ์œผ๋กœ ์ •์˜๋œ ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์“ฐ์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— new ํ‚ค์›Œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.newํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•œ ํƒ€์ž… ์ •์˜๋ฅผ ํ†ตํ•ด construct signature๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

type SomeConstructor = {
  new (s: string): SomeObject
}
function fn(ctor: SomeConstructor) {
  return new ctor("hello")
}

Generic Functions

๋ณดํ†ต param์˜ ํƒ€์ž…๊ณผ ๋ฐ˜ํ™˜๊ฐ’์˜ ํƒ€์ž…์€ ๊ด€๋ จ์ด ์žˆ๊ฑฐ๋‚˜ param๋“ค๊ฐ„์˜ ํƒ€์ž…์ด ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค. any๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ํƒ€์ž…์œผ๋กœ ์ขํ˜€์„œ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ generic์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0]
}

// s is of type 'string'
const s = firstElement(["a", "b", "c"])
// n is of type 'number'
const n = firstElement([1, 2, 3])
// u is of type undefined
const u = firstElement([])

inference

inference๋Š” ํƒ€์ž…์„ ์ง์ ‘ ์ •ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ typescript๋ฅผ ํ†ตํ•ด ์ถ”๋ก ๋˜๋Š” ํƒ€์ž…์„ ์˜๋ฏธํ•œ๋‹ค.

function map<Input, Output>(
  arr: Input[],
  func: (arg: Input) => Output
): Output[] {
  return arr.map(func)
}

const parsed = map(["1", "2", "3"], n => parseInt(n)) // parsedsms number[]์ด์•ผ

Constraints์™€ ์˜ค๋ฅ˜

generic์„ ์ด์šฉํ•ด์„œ ์—ฐ๊ด€์žˆ๋Š” input ํƒ€์ž…๋“ค์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ–ˆ์ง€๋งŒ ์–ด๋А์ •๋„ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ํƒ€์ž…์œผ๋กœ ์ขํž ์ˆ˜ ์žˆ๋‹ค. ์ขํž ๋•Œ๋Š” extends๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํƒ€์ž… ๋“ฑ์œผ๋กœ ์ขํž ์ˆ˜ ์žˆ๋‹ค.

constraint
constraint

์ด๋Ÿฐ Generic์„ ์ด์šฉํ•œ ํƒ€์ž… ์ขํžˆ๊ธฐ๋Š” ์œ ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์กฐ์‹ฌํ•ด์•ผํ•  ๋ถ€๋ถ„์ด ์žˆ๋‹ค.

constraint
constraint

์œ„ ์ฝ”๋“œ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚œ ์ด์œ ๋Š” ์šฐ๋ฆฌ Generic์œผ๋กœ ์ „๋‹ฌํ•œ ์ธ์ž์˜ ํƒ€์ž…์ด ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜๋  ๊ฒƒ๋ผ๊ณ  ์„ ์–ธํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ else๋ฌธ ์•ˆ์—๋Š” ์ขํ˜€์ง„ ๋ฒ”์œ„์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด๊ณผ ๋‹ค๋ฅธ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž…์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํฐ ์ง‘ํ•ฉ์€ ์ž‘์€ ์ง‘ํ•ฉ์— ํ• ๋‹น๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋ ‡๋‹ค๊ณ  ํฐ์ง‘ํ•ฉ์ด ์ž‘์€ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ํ•  ์ˆ˜๋Š” ์—†๋‹ค.

์‚ฌ์ž๋Š” ๋™๋ฌผ์— ํฌํ•จ๋œ๋‹ค ๋ผ๋Š”๋ง์€ ์‚ฌ์ž๊ฐ€ ๋™๋ฌผ์— ํฌํ•จ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋งž์ง€๋งŒ, ์‚ฌ์ž์™€ ๋™๋ฌผ์€ ๊ฐ™๋‹ค๋ผ๋Š” ๋ง์—๋Š” ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

Guidelines for Writing Good Generic Functions

Generic ํ•จ์ˆ˜๋ฅผ ์ž˜ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• 3๊ฐ€์ง€๋ฅผ ์ •๋ฆฌํ•ด๋ณด์ž.

  • Push Type Param Down: param์„ ๋” ๊ตฌ์ฒด์ ์ธ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
function firstElement1<Type>(arr: Type[]) {
  return arr[0]
}

function firstElement2<Type extends any[]>(arr: Type) {
  return arr[0]
}

// a: number (good)
const a = firstElement1([1, 2, 3])
// b: any (bad)
const b = firstElement2([1, 2, 3])
  • Use Fewer Type Parameters: ๋” ์ ์€ ํƒ€์ž…์˜ param์œผ๋กœ ์ด์šฉํ•œ๋‹ค.
function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
  return arr.filter(func)
}

function filter2<Type, Func extends (arg: Type) => boolean>(
  arr: Type[],
  func: Func
): Type[] {
  return arr.filter(func)
}

filter2์˜ ๊ฒฝ์šฐ๋Š” ์–ด๋–ค ํ•จ์ˆ˜ ํƒ€์ž…์ธ์ง€ ์ผ์ผ์ด ์ •ํ•ด์ค˜์•ผํ•˜๋ฏ€๋กœ ์‚ฌ์šฉ์ฒ˜์—์„œ ๋ถˆํŽธํ•จ์ด ์กด์žฌํ•œ๋‹ค.

  • Type Parameters Should Appear Twice: ์žฌ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์—๋งŒ ์ œ๋„ค๋ฆญ์„ ์“ฐ์ž.
function greet<Str extends string>(s: Str) {
  console.log("Hello, " + s)
}

greet("world")

function greet(s: string) {
  console.log("Hello, " + s)
}

ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผํ•ด๋ณด๊ณ , ๋ฐ˜๋ณต๋˜๋Š” ํƒ€์ž…์— ํ•œํ•ด์„œ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด ์ œ๋„ค๋ฆญ์„ ์“ฐ์ž.

Optional Parameters

param์ด ์—†์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด ?๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด T|undefined ๋กœ ํƒ€์ž…์ด ํ• ๋‹น๋œ๋‹ค.

function f(x?: number) {
  // ...
}
f() // OK
f(10) // OK

๋˜๋Š” param์ด ์—†์„ ๋•Œ๋ฅผ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ฐ’์„ parameter default๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

function f(x = 10) {
  // ...
}

์ฃผ์˜ํ•  ์ ์€ callback์„ ์ด์šฉํ•  ๋•Œ์˜ ์˜๋ฏธ๋Š” optionalํ•œ parameter๋Š” ํ•„์š”์—†์ด ํ˜ธ์ถœ ๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋‹ˆ๊นŒ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž.

callback
callback

Function Overloads

ํ•จ์ˆ˜ ์˜ค๋ฒ„๋กœ๋“œ๋Š” ํ‰์†Œ์— ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋˜ ๋ถ€๋ถ„์ด๋‹ค ๋ณด๋‹ˆ ์ดํ•ดํ•˜๋Š”๋ฐ ์–ด๋ ค์›€์ด ์žˆ์—ˆ๋‹ค. ํ•จ์ˆ˜ Overload๋Š” ๊ฐ™์€ ์ด๋ฆ„์˜ ํ•จ์ˆ˜์— param์ด ๋‹ค๋ฅด๊ฒŒ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

function makeDate(timestamp: number): Date
function makeDate(m: number, d: number, y: number): Date
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d)
  } else {
    return new Date(mOrTimestamp)
  }
}
const d1 = makeDate(12345678)
const d2 = makeDate(5, 5, 5)

Overload ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ์—๋Š” ๋ช‡๊ฐ€์ง€ ๊ทœ์น™์ด ์žˆ๋‹ค.

  • ์ธ์ž๊ฐ€ ์—†์„ ๋•Œ์˜ ์–ด๋–ค ํ•จ์ˆ˜์ธ์ง€ ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๋‹ค.

overload1
overload1

์œ„ ์˜ˆ์ œ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ ๋Š” param์ด ์—†์„ ๋•Œ์˜ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋ ์ง€ ์ •์˜๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์•„๋ž˜์™€ ๊ณ ์น˜๋ฉด ํƒ€์ž…์—๋Ÿฌ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

function fn(x: string): void
function fn(): void
function fn() {
  // ...
}
// Expected to be able to call with zero arguments
fn()
  • Overload ๋ผ๋ฆฌ compatibleํ•ด์•ผํ•œ๋‹ค.

overload2
overload2

์œ„ ์˜ˆ์ œ์—์„œ ๊ฐ™์€ param ๊ฐฏ์ˆ˜๋ฅผ ๊ฐ€์ง€๋Š” overload ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค. ํƒ€์ž…์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ ๋Š” ๋จผ์ € ์ž‘์„ฑํ•œ overload ํ•จ์ˆ˜ param ํƒ€์ž…์ด boolean์œผ๋กœ ์ •์˜๋œ ์ƒํ™ฉ์—์„œ ๊ฐ™์€ param ๊ฐฏ์ˆ˜๋ฅผ ๊ฐ€์ง€๋Š” ๋‘๋ฒˆ์งธ overload ํ•จ์ˆ˜์—์„œ booleanํƒ€์ž…๊ณผ compatible ํ•˜์ง€ ์•Š์€ string ํƒ€์ž…์œผ๋กœ ์ •์˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • Overload ํ•จ์ˆ˜๋Š” ์กฐ๊ฑด๋ถ€๋กœ ์“ฐ์ด๋ฉด ์•ˆ๋œ๋‹ค.
function len(s: string): number
function len(arr: any[]): number
function len(x: any) {
  return x.length
}

์œ„ ์˜ˆ์ œ๋Š” string๊ณผ array๋ฅผ param์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ overload๊ฐ€ ์ •์˜๋œ ์ƒํ™ฉ์ด๋‹ค.

overload3
overload3

์œ„ ํƒ€์ž…์—๋Ÿฌ๋Š” ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํƒ€์ž…์˜ param์„ ์ „๋‹ฌํ•˜๋Š” ์ƒํ™ฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ํ•˜๋‚˜์˜ overLoad์—์„œ๋งŒ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋Ÿด๋•Œ๋Š” param์„ ์ •์˜ํ•  ๋•Œ union type์œผ๋กœ ์ •์˜ํ•˜๋Š” ๊ฒŒ ๋” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์ด๋‹ค.

function len(x: any[] | string) {
  return x.length
}

this ๋‹ค๋ฃจ๊ธฐ

javascript์—์„œ์˜ this ์ฒ˜๋Ÿผ typescript์˜ this๋„ ๋™์ ์œผ๋กœ ์ •์˜๋œ๋‹ค.

const user = {
  id: 123,
  admin: false,
  becomeAdmin: function () {
    this.admin = true
  },
}

์œ„ ์˜ˆ์ œ์—์„œ this๋Š” ์•”์‹œ์  ๋ฐ”์ธ๋”ฉ์— ์˜ํ•ด ํ˜ธ์ถœ๋˜๋Š” ์œ„์น˜์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฐ’์„ ์˜๋ฏธํ•˜๊ฒŒ๋œ๋‹ค.

์ด๋Ÿฌํ•œ this๋ฅผ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฝ๊ฒŒ(?) ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ™”์‚ดํ‘œํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜ ์„ ์–ธ์‹๊ณผ ๋‹ค๋ฅธ ํŠน์ง•์ด ์žˆ๋Š”๋ฐ ๊ทธ์ค‘ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์“ฐ์ผ ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ž์ฒด์ ์ธ this๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๊ณ  ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์—์„œ this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ทœ์น™ ๊ฐ€์ง„๋‹ค.

this
this
์œ„ ์ฝ”๋“œ์—์„œ ํƒ€์ž… ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ ๋Š” ํ™”์‚ดํ‘œํ•จ์ˆ˜๋กœ ์ •์˜๋œ ๋ฉ”์†Œ๋“œ์˜ this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์ธ globalThis์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Other Types to Know about

๋ช‡๊ฐ€์ง€ ์•ž์„œ ์†Œ๊ฐœ๋˜์ง€ ์•Š์•˜๋˜ ํƒ€์ž…๋“ค์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด์ž.

  • Void

ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ์—†์„ ๋•Œ๋ฅผ ์œ„ํ•œ ํƒ€์ž…์œผ๋กœ, return ๋ฌธ์ด ์—†์„ ๋•Œ ์ž๋™์œผ๋กœ undefined์ด ๋ฐ˜ํ™˜๋˜์ง€๋งŒ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ๋”ฐ๋กœ void๋กœ ์ •์˜ํ•œ๋‹ค.

  • unknown

any์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ, any์™€ ๋‹ฌ๋ฆฌ ์–ด๋–ค ์†์„ฑ์„ ๊ฐ€์ง€๋Š” ์ง€ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค. ์ฃผ๋กœ try-catch ๋ฌธ์œผ๋กœ ์—๋Ÿฌ๋ฅผ ๋ฐ›์„ ๋•Œ unknown์œผ๋กœ ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„์ฆˆ๋‹ˆ์Šค ์—๋Ÿฌ๋กœ ์ ์ ˆํ•˜๊ฒŒ ํƒ€์ž…์„ ์ •์˜ํ•œ ํ›„ instanceOf ๋ฅผ ์ด์šฉํ•ด ์—๋Ÿฌ ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ˜„์—…์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

  • never

never๋Š” ์–ด๋–ค ๊ฒƒ๋„ ํฌํ•จ๋  ์ˆ˜ ์—†๋Š” ํƒ€์ž…์„ ์˜๋ฏธํ•œ๋‹ค. union์ด๋‚˜ switch๋ฌธ์—์„œ ๋”์ด์ƒ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

function fn(x: string | number) {
  if (typeof x === "string") {
    // do something
  } else if (typeof x === "number") {
    // do something else
  } else {
    x // has type 'never'!
  }
}

Rest Parameters and Arguments

Rest Parameter๋Š” ์ธ์ž๊ฐ€ ๋™์ ์œผ๋กœ ๋“ค์–ด์˜ฌ ๋•Œ์˜ param์„ ์˜๋ฏธํ•œ๋‹ค. arguments๋กœ ๋ฐ›์„ param์˜ ํƒ€์ž…๋“ค์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

function multiply(n: number, ...m: number[]) {
  return m.map(x => n * x)
}
// 'a' gets value [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4)

rest parameter๋ฅผ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์—๋Ÿฌ๋กœ๋Š” ๋ฐฐ์—ด๊ณผ ํŠœํ”Œ์˜ ํƒ€์ž… ์ฐจ์ด์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

rest
rest

์œ„ ์˜ˆ์ œ์—์„œ Math.atan2(...)๋ฉ”์†Œ๋“œ๋Š” ๋”ฑ ๋‘๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›์ง€๋งŒ args๋Š” number[]๋กœ ํƒ€์ž…์ด ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ช‡๊ฐœ์˜ ๊ฐ’์ด ๋” ๋“ค์–ด์˜ฌ์ง€ ๋ชจ๋ฅด๋Š” ํƒ€์ž…์„ ์˜๋ฏธํ•ด ์ƒ๊ธด ํƒ€์ž… ์—๋Ÿฌ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ ๋ช‡๊ฐœ์˜ ์š”์†Œ๋กœ ๋˜์–ด์žˆ๋Š” ํƒ€์ž…์ธ์ง€ ์ •์˜๋œ tuple์„ ์ด์šฉํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

const args = [8, 5] as const
// OK
const angle = Math.atan2(...args)

Parameter Destructuring

๊ฐ์ฒด param์„ ์ „๋‹ฌํ•  ๋•Œ ๊ฐ ์†์„ฑ์— ๋Œ€ํ•œ ํƒ€์ž…์„ ์ •์˜ํ•ด์„œ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

type ABC = { a: number; b: number; c: number }
function sum({ a, b, c }: ABC) {
  console.log(a + b + c)
}

Assignability of Functions

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

type voidFunc = () => void

const f1: voidFunc = () => {
  return true
}

const f2: voidFunc = () => true

const f3: voidFunc = function () {
  return true
}

์œ„ ์˜ˆ์ œ์—์„œ f1,f2,f3 ๋‹ค ๋ฐ˜ํ™˜ํ•˜๋Š” ํƒ€์ž…์ด boolean์ด์ง€๋งŒ voidFunc๋กœ ์ •์˜ํ•ด๋„ ํƒ€์ž…์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

function f2(): void {
  return true // ์—๋Ÿฌ ๋ฐœ์ƒ
}

ํ•˜์ง€๋งŒ ์ง์ ‘ ์ •์˜ํ•  ๋•Œ void๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ์ •์˜ํ•  ์‹œ์— ํƒ€์ž… ์—๋Ÿฌ๊ฐ€ ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค.

@choi2021
๋งค์ผ์˜ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ฐœ๋ฐœ์ผ์ง€์ž…๋‹ˆ๋‹ค.