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
Fix service typings #14061
Fix service typings #14061
Conversation
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 will also want to change the service declaration in packages/core/strapi/lib/global.d.ts :)
Codecov Report
@@ Coverage Diff @@
## main #14061 +/- ##
=======================================
Coverage 55.58% 55.58%
=======================================
Files 1275 1275
Lines 31833 31833
Branches 5734 5734
=======================================
Hits 17695 17695
Misses 12324 12324
Partials 1814 1814
Flags with carried forward coverage won't be shown. Click here to find out more. Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
Hi! I guess this would not require any documentation update, it will just fix things, so they work as documented in Backend customization > Services, right? |
@pwizla yep correct, just trying to fix the types, the documentation will stay the same |
Co-authored-by: Ben Irvin <ben@innerdvations.com>
@@ -20,3 +20,8 @@ export interface CollectionTypeService extends BaseService { | |||
|
|||
export type Service = SingleTypeService | CollectionTypeService; | |||
|
|||
export type GenericService = Partial<Service> & { | |||
[method: string | number | symbol]: (...args:unknown) => Promise<Entity> | Entity; |
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.
It won't necessarily return an Entity here 🙂
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.
hmmmm, should we have it be any
or unknown
?
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.
Can use a generic here:
[method: string | number | symbol]: <T = unknown>(...args:unknown) => T;
and may be better to use any
over unknown
for now since we can't have a strict type checking until we have a good typing coverage
[method: string | number | symbol]: <T = any>(...args:any) => T;
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.
@stafyniaksacha agreed probably using any would be better for now, will go with your suggestion
Hi @Bassel17! How are you? I updated to the latest version and all my methods now throw me an error: I looked for the definitions file and I modified the return type of the methods as follows: After doing this everything works perfectly, even the custom services methods (which was the reason that generated this fix). Is it possible for you to modify the return type? Thanks! |
Perhaps a return type like the following is more comprehensive:
|
@eucciferri it was already making an issue before which is why we made the return value into "any" or whatever the person chooses to type it, I'll check again |
No the error is good! It says that you have miss typed the findOne method: You used a string type whereas it needs a number for the entityId |
For now to properly infer types while using import type {
CollectionTypeService,
Service,
} from '@strapi/strapi/lib/core-api/service';
import { Strapi, factories } from '@strapi/strapi';
const custom = ({ strapi }: { strapi: Strapi }) => ({
async foo() { return 'a string' }
async bar() { return 42 }
})
const base = factories.createCoreService(
'plugin::shopify.fulfillment-order',
custom as Service
);
// this allow typescript to infer `foo` & `bar` functions with base `find`/`findOne`/....
export default base as () => CollectionTypeService & ReturnType<typeof custom>; You can check the |
Here is a shims for dynamic import {
Service,
SingleTypeService,
CollectionTypeService,
} from '@strapi/strapi/lib/core-api/service';
declare module '@strapi/strapi/lib/types/factories' {
export interface ServiceUidMap {
'plugin::foo.bar': CollectionTypeService;
'api::homepage.homepage': SingleTypeService;
[key: string]: Service;
}
export function createCoreService<K extends keyof ServiceUidMap, T>(
uid: K,
customActions?: T
): T extends undefined
? () => ServiceUidMap[K] // only base service
: T extends (...args: any) => any // custom action is function ? ({ strapi }) => ({})
? () => ReturnType<T> & ServiceUidMap[K] // merge custom action return type
: () => T & ServiceUidMap[K];
}
export {}; |
Hi @stafyniaksacha! How are you? The error is reproduced regardless of the type of data that I place in the attributes, even if it is a "string", "number" or "any". The only solution I found, as I mentioned in my previous post, was to specify the type of response that the method can throw, so I placed a Promise (in case an async method is created) of an Entity, an array of Entities or a void (in case nothing is returned). This error is always reproduced, even if you create a project from scratch and follow all the steps as indicated in the documentation, to create a new method or overwrite an existing one. Thanks. |
The error is still happening, however, doing the following fixes it I have no idea if this is desirable or not, coz I think it's up to the to decide the return type: putting export type GenericService = Partial<Service> & {
[method: string | number | symbol]: <T = any>(...args: any) => any;
};
export default factories.createCoreService('api::something.something', ({ strapi }) => {
return {
// service functions or properties here
async someFunction (a: number): Promise<number[]> {
return [1, 2, 3];
},
async someFunction2<T> (a: number): Promise<T[]> {
return [1 as T]; // to show example
},
};
}); notice the generic example at the end still works, so I am assuming that anything that is returned should work. |
Hi @emahuni, yes, it keeps getting the error for me too. I had to migrate all my services files to JavaScript in order to resolve this error. @stafyniaksacha @Bassel17 Hi guys! Could you please review this issue? |
Great news @stafyniaksacha! Thank you so much!! 😃 |
What does it do?
GenericService
type that allows the creation of custom servicesHow to test it?
Related issue(s)/PR(s)
Fixes #14035