tgoop.com/prog_way_blog/286
Create:
Last Update:
Last Update:
Как типизировать функцию мемоизации
В прошлом посте я разбирал реализацию функции мемоизации на JavaScript и упомянул, что типов там нет осознанно. В этом посте мы отдельно разберём типизацию такой функции, это будет полный разбор для самых маленьких.
Шпаргалка по используемым в посте utility-типам:
Parameters<T> - возвращает тип аргументов функции T
ReturnType<T> - возвращает тип возвращаемых значений функции T
const foo = (a: number , b: number) => 5
type Args = Parameters<typeof foo>
// [a: number, b: number]
type Return = ReturnType<typeof foo>
// number
Итак, наша функция принимает в себя другую функцию. Сразу же типизируем это:
function memoize(func: (...args: any[]) => any) {
// ...
}
Далее было бы неплохо типизировать возвращаемую функцию. Для этого мы можем использовать следующую конструкцию:
(...args: Parameters<оригинальная функция>) => ReturnType<оригинальная функция>
. И вот мы сталкиваемся с проблемой, что для корректной типизации возвращаемой функции нам необходимы типы Parameters
и ReturnType
, которые обязательно принимают дженерик. В качестве дженерика выступает тип оригинальной функции. Для удобства вынесем тип оригинальной функции в дженерик функции memoize
:function memoize<T extends (...args: any[]) => any>(func: T) {
// ...
}
И итоговый интерфейс функции у нас сильно растянется, но будет таким:
type AnyFunction = (...args: any[]) => any;
type MemoizedFunction<T extends AnyFunction> =
(...args: Parameters<T>) => ReturnType<T>
function memoize<T extends AnyFunction>(func: T): MemoizedFunction {
// ...
}
Ребята, стараюсь максимально упростить. Если плохо понимаете дженерики, постарайтесь более внимательно вчитываться в код.
Далее типизация кэша, тут всё просто:
const cache = new Map<string, ReturnType<T>>();
По типизации, ключ — строка, а значение — тот тип, который возвращает оригинальная функция.
Далее рассмотрим итоговый код:
type AnyFunction = (...args: any[]) => any;
type MemoizedFunction<T extends AnyFunction> =
(...args: Parameters<T>) => ReturnType<T>
function memoize<T extends AnyFunction>(func: T): MemoizedFunction {
const cache = new Map<string, ReturnType<T>>();
return function(...args: Parameters<T>): ReturnType<T> {
const key = JSON.stringify(args);
if (!cache.has(key)) {
cache.set(key, func(...args));
}
return cache.get(key)!;
};
}
Надеюсь вышло понятно. Если что, любые вопросы можем обсудить в комментариях.
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #code #typescript
BY progway — программирование, IT
Share with your friend now:
tgoop.com/prog_way_blog/286