diff --git a/src/curry/memo.ts b/src/curry/memo.ts index 363e338f..e3611b8a 100644 --- a/src/curry/memo.ts +++ b/src/curry/memo.ts @@ -1,3 +1,5 @@ +import type { NoInfer } from 'radashi' + type Cache = Record function memoize( @@ -56,7 +58,7 @@ export interface MemoOptions { */ export function memo( func: (...args: TArgs) => TResult, - options: MemoOptions = {}, + options: MemoOptions> = {}, ): (...args: TArgs) => TResult { return memoize({}, func, options.key ?? null, options.ttl ?? null) } diff --git a/src/types.ts b/src/types.ts index 786d2695..330c900c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -37,6 +37,13 @@ export type ExtractNotAny = Extract<[T] extends [Any] ? never : T, U> export type SwitchAny = [T] extends [Any] ? U : T export type SwitchNever = [T] extends [never] ? U : T +/** + * Prevent type inference on type `T`. + * + * @see https://github.com/microsoft/TypeScript/issues/14829#issuecomment-504042546 + */ +export type NoInfer = [T][T extends any ? 0 : never] + /** * Extract types in `T` that are assignable to `U`. Coerce `any` and * `never` types to unknown. diff --git a/tests/curry/memo.test-d.ts b/tests/curry/memo.test-d.ts new file mode 100644 index 00000000..66ac7705 --- /dev/null +++ b/tests/curry/memo.test-d.ts @@ -0,0 +1,18 @@ +import * as _ from 'radashi' + +describe('memo return type', () => { + test('memo with single argument key function', () => { + const foo = _.memo((a: string, b?: string) => {}, { key: a => a }) + expectTypeOf(foo).toEqualTypeOf< + (a: string, b?: string | undefined) => void + >() + }) + + test('memo with two argument key function', () => { + const foo = _.memo((a: string, b?: string) => {}, { key: (a, b) => a }) + expectTypeOf(foo).toEqualTypeOf< + (a: string, b?: string | undefined) => void + >() + foo('a') + }) +})