Jieunnyμ λΈλ‘κ·Έ
[TS] ν¨μ μ‘°ν©μ μ리μ μμ© λ³Έλ¬Έ
π£ ν¨μν νλ‘κ·Έλλ°μ΄λ?
βοΈ ν¨μν νλ‘κ·Έλλ° : μμ ν¨μμ μ μΈν νλ‘κ·Έλλ°μ ν λ μμ 'ν¨μ μ‘°ν©' κ³Ό 'λͺ¨λλ μ‘°ν©'μΌλ‘ μ½λλ₯Ό μ€κ³νκ³ κ΅¬ννλ κΈ°λ²
β° ν¨μν νλ‘κ·Έλλ° μΈμ΄λ μ μ νμ , νμ μΆλ‘ λ±μ κΈ°λ°μ λ κ³ μ°¨ νμ , ν¨ν΄ λ§€μΉ λ±μ κ³ κΈ κΈ°λ₯μ μ 곡νλ€.
π£ μ λ€λ¦ ν¨μ
βοΈ number μ κ°μ νμ μ νμ λ³μ Tλ‘ νκΈ°ν λ μ΄λ₯Ό 'μ λ€λ¦ νμ ' μ΄λΌκ³ νλ€.
β° ν¨μ μ‘°ν©μ ꡬνν λλ μ λ€λ¦ ν¨μ ꡬ문μ μ¬μ©ν΄μΌ νλ€.
π νμ μ€ν¬λ¦½νΈμ μ λ€λ¦ ν¨μ ꡬ문
function g1<T>(a: T): void {}
β° μ λ€λ¦ νμ μΌλ‘ ν¨μλ₯Ό μ μνλ©΄ μ΄λ€ νμ μλ λμν μ μλ€.
β° g1 ν¨μλ a 맀κ°λ³μκ° μ λ€λ¦ νμ μΌλ‘ μ§μ λμλ€.
type Type1Func<T> = (T) => void
type Type2Func<T, Q> = (T, Q) => void
type Type3Func<T, Q, R> = (T, Q) => R
// Type3Func ν¨μμ μκ·Έλμ²λ Tμ Qνμ
κ°μ μ
λ ₯λ°μ R νμ
κ°μ λ°ννλ κ²μ μλ―Ένλ€.
β° νμ λ³μΉμ μ λ€λ¦ νμ μ μ μ©ν μ μλ€.
π ν¨μμ μν
β° ν¨μ fκ° T νμ μ xκ°μΌλ‘ R νμ μ yκ°μ λ§λ λ€.
(x: T) ~-> f -> (y: R)
β° μ΄λ° κ΄κ³λ₯Ό μΌλμΌ κ΄κ³λΌκ³ νκ³ , μ΄λ° λμμ νλ ν¨μλ₯Ό '맡(map)'μ΄λΌκ³ νννλ€.
type MapFunc<T, R> = (T) => R
β° νμ TμΈ κ°μ μ΄μ©ν΄ νμ RμΈ κ°μ λ§λ€μ΄μ£Όλ ν¨μμ μκ·Έλμ²
π μμ΄λ΄ν°ν° ν¨μ
Ⱐ맡 ν¨μμ κ°μ₯ λ¨μν ννλ μ λ ₯κ° xλ₯Ό κ°κ³΅ μμ΄ κ·Έλλ‘ λ°ννλ κ²μ΄λ€.
β° μ΄λ¬ν μν μ νλ ν¨μμ μ΄λ¦μλ λ³΄ν΅ identity λλ IλΌλ λ¨μ΄κ° ν¬ν¨λλ€.
type MapFunc<T, R> = (T) => R
type IdentityFunc<T> = MapFunc<T, T>
const numberIdentity: IdentityFunc<number> = (x: number): number => x
const stringIdentity: IdentityFunc<string> = (x: string): string => x
β° μ μν μ λ€λ¦ ν¨μ IdentityFunc<T>λ λ€μν ν¨μλ₯Ό μ μΈν λ μ¬μ©ν μ μλ€.
π£ κ³ μ°¨ ν¨μμ 컀리
βοΈ ν¨μμμ 맀κ°λ³μμ κ°μλ₯Ό μ 리ν°(arity) λΌκ³ νλ€.
β° κ° ν¨μμ μ 리ν°κ° κ°λ€λ©΄ μ°κ²°ν΄μ μ¬μ©ν μ μλ€.
y = h(g(f(x)))
β° ν¨μν νλ‘κ·Έλλ°μμλ compose λ pipe ν¨μλ₯Ό μ¬μ©ν΄μ ν¨μλ€μ μ‘°ν©ν΄ μλ‘μ΄ ν¨μλ₯Ό λ§λ€ μ μλ€.
π κ³ μ°¨ ν¨μλ?
β° νμ μ€ν¬λ¦½νΈμμ ν¨μλ λ³μμ λ΄κΈ΄ ν¨μ ννμμ΄κ³ ν¨μ ννμμ΄λ μΌμ’ μ κ°μ΄κΈ° λλ¬Έμ ν¨μμ λ°νκ°μΌλ‘ ν¨μλ₯Ό μ¬μ©ν μ μλ€.
β° μ΄λ€ ν¨μκ° λ λ€λ₯Έ ν¨μλ₯Ό λ°νν λ κ·Έ ν¨μλ₯Ό 'κ³ μ°¨ ν¨μ' λΌκ³ νλ€.
β° ν¨μκ° μλ λ¨μν κ°μ λ°ννλ ν¨μλ '1μ°¨ ν¨μ' λΌκ³ νλ€.
1μ°¨ ν¨μλ₯Ό λ°ννλ©΄ '2μ°¨ κ³ μ°¨ ν¨μ', 2μ°¨ ν¨μλ₯Ό λ°ννλ©΄ '3μ°¨ κ³ μ°¨ ν¨μ' λΌκ³ νλ€.
type FirstOrderFunc<T, R> = (T) => R
// R νμ
μ κ°μ λ°ννλ 1μ°¨ ν¨μ
type SecondOrderFunc<T, R> = (T) => FirstOrderFunc<T, R>
// 1μ°¨ ν¨μλ₯Ό λ°ννλ 2μ°¨ κ³ μ°¨ν¨μ
type ThirdOrderFunc<T, R> = (T) => SecondOrderFunc<T, R>
// 2μ°¨ ν¨μλ₯Ό λ°ννλ 3μ°¨ κ³ μ°¨ν¨μ
const inc: FirstOrderFunc<number, number> = (x: number): number => x + 1
inc(1) // 1μ°¨ ν¨μμ΄λ―λ‘ ν¨μ νΈμΆ μ°μ°μλ₯Ό ν λ² μ¬μ©νλ€.
β° inc ν¨μλ λ¨μν number νμ μ κ°μ λ°ννλ―λ‘ 1μ°¨ ν¨μμ΄λ€.
const add: SecondOrderFunc<number, number> =
(x: number): FirstOrderFunc<number, number> =>
(y: number): number => x + y
add(1)(2)
// 2μ°¨ κ³ μ°¨ ν¨μλ₯Ό νΈμΆν λλ ν¨μ νΈμΆ μ°μ°μλ₯Ό λ λ² μ°μ μ¬μ©νλ€.
β° add ν¨μλ FirstOrderfunc<number, number> ν¨μλ₯Ό λ°ννλ―λ‘ 2μ°¨ κ³ μ°¨ ν¨μμ΄λ€.
β° ν¨μ νΈμΆ μ°μ°μλ₯Ό μ°μμΌλ‘ μ¬μ©νλ κ²μ '컀리(curry)' λΌκ³ νλ€.
const add3: ThirdOrderFunc<number, number> =
(x: number): SecondOrderFunc<number, number> =>
(y: number): FirstOrderFunc<number, number> =>
(z: number): number -> x + y + z
add3(1)(2)(3)
// 3μ°¨ κ³ μ°¨ ν¨μλ ν¨μ νΈμΆ μ°μ°μλ₯Ό μΈ λ² μ΄μ΄ λΆμ΄ νΈμΆνλ€.
β° add3 ν¨μλ FirstOrderFunc ν¨μλ₯Ό λ°ννλ SecondOrderFunc ν¨μλ₯Ό λ°ννλ―λ‘ 3μ°¨ κ³ μ°¨ ν¨μμ΄λ€.
π λΆλΆ μ μ© ν¨μμ 컀리
β° κ³ μ°¨ ν¨μλ€μ μμ μ μ°¨μλ§νΌ ν¨μ νΈμΆ μ°μ°μλ₯Ό μ°λ¬μ μ¬μ©νλ€.
β° μμ μ μ°¨μλ³΄λ€ ν¨μ νΈμΆ μ°μ°μλ₯Ό μ κ² μ¬μ©νλ©΄ 'λΆλΆ μ μ© ν¨μ' λλ 'λΆλΆ ν¨μ' λΌκ³ νλ€.
const add1: SecondOrderFunc<number, number> = add(1)
// add1μ λΆλΆ ν¨μμ΄λ€.
add1(2)
add(1)(2)
// add1μ add(1)κ³Ό λκ°λ€.
β° add1μ 1μ°¨ ν¨μμ΄λ―λ‘ ν¨μ νΈμΆ μ°μ°μλ₯Ό 1κ° μ¬μ©ν΄ μΌλ° ν¨μμ²λΌ νΈμΆν μ μλ€.
β° add1(2)λ‘ νΈμΆνλ©΄ add(1)κ³Ό ν¨κ» μ λ¬λμ 3μ΄ μΆλ ₯λλ€.
π ν΄λ‘μ
β° κ³ μ°¨ ν¨μμ λͺΈν΅μμ μ μΈλλ λ³μλ€μ ν΄λ‘μ (closure)λΌλ μ ν¨ λ²μλ₯Ό κ°μ§λ€.
β° ν΄λ‘μ λ 'μ§μλλ μ ν¨ λ²μ' λ₯Ό μλ―Ένλ€.
function add(x: number): (number) => number { // λ°κΉ₯μͺ½ μ ν¨ λ²μ μμ
return function(y: number): number { // μμͺ½ μ ν¨ λ²μ μμ
return x + y // ν΄λ‘μ
} // μμͺ½ μ ν¨ λ²μ λ
} // λ°κΉ₯μͺ½ μ ν¨ λ²μ λ
β° return x + y λΆλΆμ add ν¨μκ° λ°ννλ ν¨μμ λ°νλ¬ΈμΈλ°, μ΄ ν¨μλ μμ μ λ°κΉ₯μͺ½ μ ν¨ λ²μμ μλ λ³μ xλ₯Ό μ°Έμ‘°νκ³ μλ€.
β° addκ° λ°ννλ ν¨μμμ λ³Ό λ xλ μ΄ν΄ν μ μλ λ³μμ΄λ©°, μ΄μ²λΌ λ²μ μμμλ κ·Έ μλ―Έλ₯Ό μ μ μλ λ³μλ₯Ό 'μμ λ³μ' λΌκ³ λΆλ₯Έλ€.
β° νμ μ€ν¬λ¦½νΈλ μμ λ³μκ° μμΌλ©΄ κ·Έ λ³μμ λ°κΉ₯μͺ½ μ ν¨ λ²μμμ μμ λ³μμ μλ―Έ(μ μΈλ¬Έ)μ μ°Ύλλ€.
const add1 = add(1) // λ³μ x λ©λͺ¨λ¦¬ μ μ§
β° add ν¨μλ₯Ό νΈμΆνλλΌλ λ³μ xμ λ©λͺ¨λ¦¬κ° ν΄μ λμ§ μκΈ° λλ¬Έμ ν΄λ‘μ λ₯Ό μ§μλλ μ ν¨ λ²μλΌκ³ λΆλ₯΄λ κ²μ΄λ€.
const result = add1(2) // resultμ 3μ μ μ₯ ν λ³μ x λ©λͺ¨λ¦¬ ν΄μ
β° μ΄μ²λΌ κ³ μ°¨ ν¨μκ° λΆλΆ ν¨μκ° μλ 'κ°'μ λ°μν΄μΌ λΉλ‘μ μμ λ³μμ λ©λͺ¨λ¦¬κ° ν΄μ λλ μ ν¨ λ²μλ₯Ό 'ν΄λ‘μ 'λΌκ³ νλ€.
const MakeNames = (): () => string => { // λ°κΉ₯μͺ½ μ ν¨ λ²μ
const names = ['Jack', 'Jane', 'Smith']
let index = 0
return (): string => { // μΈμͺ½ μ ν¨ λ²μ
if(index == names.length)
index = 0
return names[index++]
}
}
const makeName: () => string = makeNames()
console.log(
[1, 2, 3, 4, 5, 6].map(n => makeName())
}
//['Jack', 'Jane', 'Smith', 'Jack', 'Jane', 'Smith']
β° makeNames ν¨μλ₯Ό νΈμΆνλ©΄ () => string νμ μ ν¨μ makeNameμ μ»λλ€.
β° λ°°μ΄μ map ν¨μλ₯Ό μ€νν΄μ κ° μμμ makeName() ν¨μλ₯Ό μ€ννλ©΄ λ°°μ΄μ μμ΄ν μλ§νΌ μ΄ μ¬μ― λ² makename() ν¨μκ° νΈμΆλλ€.
β° indexλ names.lengthμ κ°μ΄ κ°μμ§λ©΄ λ€μ 0μ΄ λλ―λ‘ makeName ν¨μλ₯Ό μ¬μ©νλ ν makeNames ν¨μμ ν λΉλ ν΄λ‘μ λ ν΄μ λμ§ μλλ€.
π£ ν¨μ μ‘°ν©
βοΈ ν¨μ μ‘°ν© : μμ κΈ°λ₯μ ꡬνν ν¨μλ₯Ό μ¬λ¬ λ² μ‘°ν©ν΄ λ μλ―Έ μλ ν¨μλ₯Ό λ§λ€μ΄ λ΄λ νλ‘κ·Έλ¨ μ€κ³ κΈ°λ²
β° ν¨μ μ‘°ν©μ ν μ μλ ν¨μ : compose, pipe
π compose ν¨μ
β° κ°λ³ μΈμ μ€νμΌλ‘ ν¨μλ€μ λ°°μ΄μ μ λ ₯λ°λλ€.
β° ν¨μλ€μ μ‘°ν©ν΄ 맀κ°λ³μ xλ₯Ό μ λ ₯λ°λ 1μ°¨ ν¨μλ₯Ό λ°ννλ€.
const compose = <T, R>(...functions: readonly Function[]): Function => (x:T): (T) => R => {
const deepCopiedFunctions = [...functions]
return deepCopiedFunctions.reverse().reduce((value, func) => func(value), x)
}
const composedFGH = compose(h, g, f)
conposedFGH('x')
// h(g(f(x)))
β° compose(h, g, f)λ‘ λ§λ composedFGHλ 1μ°¨ ν¨μμ΄λ―λ‘ μΌλ° ν¨μμ²λΌ νΈμΆν μ μλ€.
const inc = x => x + 1
const composed = compose(inc, inc, inc)
composed(1) // 4
β° composeμ λμμΌλ‘ 1 -> inc -> 2 -> inc -> 3 -> inc -> 4 μ κ³Όμ μ΄ λ°μνλ€.
β° 1μ κ°μ§κ³ inc ν¨μκ° μΈ λ² μ°λ¬μ νΈμΆλλ©΄μ κ²°κ΄κ° 4κ° λμ¨λ€.
π pipe ν¨μ
β° composeμ λμ μ리λ κ°μ§λ§, μ‘°ν©νλ ν¨μλ€μ μμλ§ λ°λμ΄λ€.
const pipe = <T>(...functions: readonly Function[]): Function => (x:T): T => {
return functions.reduce((value, func) => func(value), x)
}
const piped = pipe(f, g, h)
piped('x')
// h(g(f(x)))
β° composeμ λ¬λ¦¬ 맀κ°λ³μλ‘ μ λ¬λ ν¨μλ₯Ό λ€μμλΆν° μ μ©νλ€.
π pipe μ compose ν¨μ λΆμ
β° ν¨μλ€μ μκ·Έλμ²κ° κ°κ° λͺ¨λ λ€λ₯΄λ©΄ κ°λ³ μΈμ functionsμ νμ μ μ€μ νκΈ° μ΄λ ΅λ€.
β° λλ¬Έμ functionsμ μλ°μ€ν¬λ¦½νΈ νμ Functionλ€μ λ°°μ΄μΈ Function[]μΌλ‘ μ€μ νλ€.
β° pipe ν¨μλ functions λ°°μ΄μ μ‘°ν©ν΄ μ΄λ€ ν¨μλ₯Ό λ°νν΄μΌ νλ―λ‘ λ°ν νμ μ FunctionμΌλ‘ μ€μ νλ€.
β° pipe ν¨μλ‘ μ‘°ν©λ κ²°κ³Ό ν¨μμ μ 리ν°λ 1μ΄λ©°, κ·Έ 맀κ°λ³μ xμ νμ μ μ λ€λ¦ νμ μΈ Tλ‘ μ€μ νλ€.
β° ν¨μ λͺΈν΅μ reduce ν¨μλ₯Ό μ¬μ©ν΄μ 맀κ°λ³μμΈ λ³μ xλ₯Ό μ΄κΉκ°μΌλ‘ λλ€.
β° reduce λ©μλμ μ½λ°± ν¨μ λΆλΆμ (value, func) ννμ 맀κ°λ³μ ꡬ쑰λ₯Ό κ°μ ΈμΌ νλ€.
const pipe = (...functions: Function[]): Function =>(x: T) => T => {
return functions.reduce((value, func) => func(value), x)
}
β° compose ν¨μλ pipe ν¨μμ 맀κ°λ³μ λ°©ν₯μ΄ λ°λμ΄λ―λ‘ functions.reverse()λ₯Ό νΈμΆνλ μ½λλ₯Ό μΆκ°ν΄μ£Όλ©΄ λλ€.
β° νμ§λ§ composeλ μμ ν¨μμ λͺ¨μ΅μΌλ‘ λμν΄μΌ νλ―λ‘ functionsμ μ κ° μ°μ°μλ‘ μ κ°ν΄μ κΉμ 볡μ¬λ₯Ό ν΄μ€λ€.
const compose = <T>(...functions: readnly Function[]): Function => (x:T) :T => {
const deepCopiedFunctions = [...functions]
deepCopiedFunctions.reverse().reduce((value, func) => func(value), x)
}
π λΆλΆ ν¨μμ ν¨μ μ‘°ν©
β° κ³ μ°¨ ν¨μμ λΆλΆ ν¨μλ ν¨μ μ‘°ν©μ μ¬μ©λ μ μλ€.
const add = x = > y => x + y
const inc = add(1)
const add3 = pipe(
inc,
add(2)
}
console.log(
add3(1) //4
}
β° inc ν¨μλ addμ λΆλΆ ν¨μμ΄λ€.
β° add3μ pipe ν¨μλ₯Ό κ°μ§κ³ incμ add(2)λ₯Ό μ‘°ν©ν΄μ λ§λ ν¨μμ΄λ€.
β° add3μ μΌλ° ν¨μ μ΄λ―λ‘ add3(1)λ‘ νΈμΆνλ©΄, inc ν¨μκ° νΈμΆλμ΄ κ° 1μ 2κ° λκ³ , add(2)μ μν΄ μ΅μ’ 4λΌλ κ°μ΄ λλ€.
π ν¬μΈνΈκ° μλ ν¨μ
β° ν¨μ μ‘°ν©μ κ³ λ €ν΄ μ€κ³ν ν¨μλ₯Ό 'ν¬μΈνΈκ° μλ ν¨μ' λΌκ³ νλ€.
const map = f => a => a.map(f)
// map ν¨μλ fλΌλ ν¨μλ₯Ό λ°λλ°, fλΌλ ν¨μλ aλΌλ 맀κ°λ³μλ₯Ό λ°κ³ , κ·Έ 맀κ°λ³μμ fλΌλ ν¨μλ₯Ό μ μ©νλ€.
β° map(f) ννμ λΆλΆ ν¨μλ₯Ό λ§λ€λ©΄ composeλ pipeμ μ¬μ©ν μ μλ€.
const square = value => value * value
const squaredMap = map(square)
// const squaredMap = a => map(square)(a)
β° μ£Όμ λΆλΆκ³Όλ λ¬λ¦¬ κ΅³μ΄ aλ₯Ό μ§μ νμ§ μλ κ²μ΄ ν¬μΈνΈκ° μλ€λ κ²μ΄λ€.
const fourSquare = pipe(
squaredMap,
squaredMap
)
console.log(
fourSquare([3, 4]) // [82, 256] [(3*3)*(3*3), (4*4)*(4*4)]
)
'Study > TypeScript' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[TS] Exercises 4 (0) | 2023.07.19 |
---|---|
[TS] Exercises 1~3 (0) | 2023.07.18 |
[TS] Promiseμ async/await ꡬ문 (0) | 2023.02.06 |
[TS] λ°λ³΅κΈ°μ μμ±κΈ° (0) | 2023.02.03 |
[TS] λ°°μ΄κ³Ό νν (2) | 2023.02.02 |