-
Notifications
You must be signed in to change notification settings - Fork 0
feat(typescript): migrate to typescript #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/index.ts
Outdated
| /* eslint-disable @typescript-eslint/ban-types */ | ||
| interface MemoizeOptions { | ||
| // useCached: Will return the last resolved cached value | ||
| useCached?: true | false | Function; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: How do i say that this Function would be called with a single parameter matching CacheItem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would (param: CacheItem) => void work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Mejsun 👍
src/index.ts
Outdated
| getKey?: Function; | ||
|
|
||
| // cache: Caching Map | ||
| cache?: Map<string | number | symbol, any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Map key definition seems a bit verbose, and possibly incomplete, does anyone know a better way?
src/index.ts
Outdated
|
|
||
| // getKey: Default key definition | ||
| // eslint-disable-next-line @typescript-eslint/ban-types | ||
| getKey?: Function; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function should define any function which takes an an unknown number and type of parameters. And returns something that can be used as a Map Key. How would i define such a thing... and would it be just as flexible as Function here?
src/index.ts
Outdated
| * @returns {Promise} Value of the callback | ||
| */ | ||
| return async (...args) => { | ||
| return async (...args: any) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: How do i remove the any here?
I want it to infer the parameter Types which are acceptable by the other parameter function callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need a generic for TS to infer this.
Define the memoise function like so:
export default function Memoize<ParameterTypes extends Array<unknown>>(
callback: (...args: ParameterTypes) => unknown,
opts: MemoizeOptions = {}
) {Then you can use the ParameterTypes generic here:
| return async (...args: any) => { | |
| return async (...args: ParameterTypes) => { |
Might also be worth replacing all the anys in this file with unknown, TS is stricter about what you can do with that, and if you don't really care about those types, it's just as good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to keep the separate MemoizeCallback type, define it like so and pass through the generic:
type MemoizeCallback<ParameterTypes extends Array<unknown>> = (
...args: ParameterTypes
) => unknown;
export default function Memoize<ParameterTypes extends Array<unknown>>(
callback: MemoizeCallback<ParameterTypes>,
opts: MemoizeOptions = {}
) {But I'd argue it's not worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing I just thought about – it might be nice to be able to work with the return type of the callback, eg. like so:
export default function Memoize<
ParameterTypes extends Array<unknown>,
CallbackValue extends Promise<unknown>
>(
callback: (...args: ParameterTypes) => CallbackValue,
opts: MemoizeOptions<ParameterTypes, CallbackValue> = {}
) {Though this implies the function can only be used with async functions, not sure if that is intended.
In any case this will make sure that the memoised function keeps its return type.
src/index.ts
Outdated
| interface MemoizeOptions { | ||
| // useCached: Will return the last resolved cached value | ||
| useCached?: true | false | MemoizeUseCacheHandler; | ||
|
|
||
| // staleInMs: How long before we should check for new updates | ||
| staleInMs?: number; | ||
|
|
||
| // getKey: Default key definition | ||
| getKey?: (...args: any) => MemoizeCacheKey; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also weave the ParameterTypes from my earlier suggestion through to the options and use it there:
| interface MemoizeOptions { | |
| // useCached: Will return the last resolved cached value | |
| useCached?: true | false | MemoizeUseCacheHandler; | |
| // staleInMs: How long before we should check for new updates | |
| staleInMs?: number; | |
| // getKey: Default key definition | |
| getKey?: (...args: any) => MemoizeCacheKey; | |
| interface MemoizeOptions<ParameterTypes extends Array<unknown>> { | |
| // useCached: Will return the last resolved cached value | |
| useCached?: true | false | MemoizeUseCacheHandler; | |
| // staleInMs: How long before we should check for new updates | |
| staleInMs?: number; | |
| // getKey: Default key definition | |
| getKey?: (...args: ParameterTypes) => MemoizeCacheKey; |
src/index.ts
Outdated
| // cache Max Size | ||
| cacheMaxSize = 1000, | ||
| } = opts; | ||
| }: MemoizeOptions = opts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TS should be able to infer this even if you remove it.
src/index.ts
Outdated
| return async (...args) => { | ||
| return async (...args: any) => { | ||
| // Serialize the keys... | ||
| const key = getKey(...args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interestingly, TS flags this with the error A spread argument must either have a tuple type or be passed to a rest parameter. And it seems to have a point: If the callback function has multiple parameters, does it make sense to pass those to e.g. JSON.stringify as individual params?
Maybe they should be passed like so?
| const key = getKey(...args); | |
| const key = getKey(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried your implementation... this certainly proves a sticking point. I would like to to have the same parameter structure as the callback function. But yes, Typescript is happier if i pass this through as an array of the first parameter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, maybe there's a way to shut up that TS error.
BREAKING CHANGE: this changes the getKey parameters 😭
# [2.0.0](v1.4.7...v2.0.0) (2023-03-17) ### Features * **typescript:** migrate to typescript ([#56](#56)) ([52fa531](52fa531)) ### BREAKING CHANGES * **typescript:** this changes the getKey parameters 😭 * chore(deps): update deps * feat(ts): add callback values, noissue * chore: rm editorconfig * chore(lint): fix lint * chore(ts): remove deprecation warnings BREAKING CHANGES: Change in the `options.getKey(...args)` => `options.getKeys(args)` args is contained in first parameter.
|
🎉 This PR is included in version 2.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Migrate to TS