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λ₯Ό ν΅ν΄ ν΄λΉ μμ±μ κ°μ§κ³ μλ νμ λ±μΌλ‘ μ’ν μ μλ€.
μ΄λ° Genericμ μ΄μ©ν νμ μ’νκΈ°λ μ μ©ν μ μμ§λ§ μ‘°μ¬ν΄μΌν λΆλΆμ΄ μλ€.
μ μ½λμμ μλ¬κ° λ μ΄μ λ μ°λ¦¬ 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λ νμμμ΄ νΈμΆ λ μ μμμ μλ―Ένλ κ²μ΄λκΉ λΆνμνκ² μ¬μ©νμ§ λ§μ.
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 ν¨μλ₯Ό μμ±νλλ°μλ λͺκ°μ§ κ·μΉμ΄ μλ€.
- μΈμκ° μμ λμ μ΄λ€ ν¨μμΈμ§ ꡬνμ΄ νμνλ€.
μ μμ μμ μλ¬κ° λ°μν μ΄μ λ paramμ΄ μμ λμ ν¨μκ° μ΄λ»κ² ꡬνλ μ§ μ μλμ§ μμκΈ° λλ¬Έμ΄λ€.
μλμ κ³ μΉλ©΄ νμ μλ¬κ° μ¬λΌμ§λ κ²μ λ³Ό μ μλ€.
function fn(x: string): void
function fn(): void
function fn() {
// ...
}
// Expected to be able to call with zero arguments
fn()
- Overload λΌλ¦¬ compatibleν΄μΌνλ€.
μ μμ μμ κ°μ 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κ° μ μλ μν©μ΄λ€.
μ νμ μλ¬λ 쑰건μ λ°λΌ λ€λ₯Έ νμ μ 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λ μμ μ€μ½νμΈ 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λ₯Ό μκΈΈ μ μλ νμ μλ¬λ‘λ λ°°μ΄κ³Ό ννμ νμ μ°¨μ΄μμ λ°μν μ μλ€.
μ μμ μμ 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λ₯Ό λ°ννλ€κ³ μ μν μμ νμ μλ¬κ° κ±Έλ¦¬κ² λλ€.