🐕

【TS/JS】高階関数に関数を渡す際のテクニック

1 min read

ライブラリの関数を自分で定義した高階関数に渡してやる際、型が違って困る時ってありますよね?
そんな時のテクニックです。

本記事では以下のように関数の型を定義します。

type Reader<A, B> = (args: A) => B;

次に、このようなライブラリ関数があるとします。

type Library<A,B extends Object> = Reader<A, B & {sample: string}>

const libraryFun: Library<number, {number: number}> = n => ({
    number: n*8 - 12,
    sample: n.toString()
})

そして私は、コードのボイラープレートを削減するために共通の処理をまとめる以下のようなラッパー関数を定義したとします。

const wrapper = (wrapped: Reader<number, number>): Reader<number, string> => (item => {

    const x = wrapped(item)
    
    const y = x*2 +10

    return (y+1).toString()
})

ここで「libraryFun」の計算結果を利用するため、「wrapper」に「libraryFun」を渡そうとすると、型が違うため渡せません。

そこで以下のように関数を拡張するコンテナクラスを用意します。

class Container<A,B> {
    constructor(readonly fn: Reader<A, B>){}

    map = <C>(applyFun: Reader<B,C>): Reader<A,C> => args => applyFun(this.fn(args))

}

そうするとこのように書けます。

const wrapped: Reader<number, number> = new Container(libraryFun).map(item => item.number)
const fn: Reader<number, string> = wrapper(wrapped)
console.log(1)  
// 3

Discussion

ログインするとコメントできます