Skip to content
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

Feathers Typescript - Typed HookContext #1952

Open
EmirGluhbegovic opened this issue May 10, 2020 · 1 comment
Open

Feathers Typescript - Typed HookContext #1952

EmirGluhbegovic opened this issue May 10, 2020 · 1 comment

Comments

@EmirGluhbegovic
Copy link

@EmirGluhbegovic EmirGluhbegovic commented May 10, 2020

Steps to reproduce

There is an issue titled similar to mine, but it drifts to typing the sequelize models.

My goals:

  • Be able to do app.get([typed options appear here])
  • Be able to do app.service([typed options appear here]) -> this does not happen when using HookContext

In my attempt to solve this I tried the following:

in the declarations.d.ts file:

imports....
  import config from '@config/default.json';
 declarations...

// A mapping of service names to types. Will be extended in service files.
export interface EntityServices {
	users: Service<UserInterface>;
	subscribers: Service<SubscriberInterface>;
	permissions: Service<PermissionInterface>;
}

type Config = typeof config;

interface ModifiedConfig extends Config {
	sequelizeClient: Sequelize.Sequelize;
	'view engine': 'ejs';
}

export interface ServiceTypes extends EntityServices {}

type initialApplication = ExpressFeathers<ServiceTypes>;

type AppGet = <T extends keyof ModifiedConfig>(path: T) => ModifiedConfig[T];
type AppSet = <T extends keyof ModifiedConfig>(
	path: T,
	config: ModifiedConfig[T],
) => initialApplication;

// The application instance type that will be used everywhere else
export interface Application extends Omit<initialApplication, 'get' | 'set'> {
	get: AppGet;
	set: AppSet;
}

export type Paths = keyof ServiceTypes;
export type EntityPaths = keyof EntityServices;

export interface APIHookContext extends FeathersHookContext {
	app: Application;
	path: Paths;
}

export interface HookContext extends FeathersHookContext {}

This initially works perfectly but the issue comes in the use:

In a hook function if I change:

This:

export const sendNewUserEmail = async (context: HookContext) => { [some code...] return context; };

To this:

export const sendNewUserEmail = async (context: APIHookContext) => { [some code...] return context; };

I get all of typing BUT, all hell breaks loose with some of the following:

The service.hooks(hooks); call, now complains of a mismatch between the application and paths object of APIHookContext and HookContext.

On deeper inspection I see within the feathers typing, HookContext refers to "this", which I believe is the uninitialized application. Hence my object is populated while "this" is empty.

I tried further by extracting the service.hooks() function and updating its type but then the issue arises with feathers imports such as "feathers-hooks-common" functions. They pass HookContext which then does not match with APIHookContext.

A sample of the type error on the service.hooks function:

...type '(((context: HookContext<any, Service<any>>) => Promise<HookContext<any, Service<any>>>) | ((context: APIHookContext) => Promise<...>))[]' is not assignable to type 'Hook<any, Service<any>>[]'. Type '((context: HookContext<any, Service<any>>) => Promise<HookContext<any, Service<any>>>) | ((context: APIHookContext) => Promise<...>)' is not assignable to type 'Hook<any, Service<any>>'. Type '(context: APIHookContext) => Promise<APIHookContext>' is not assignable to type 'Hook<any, Service<any>>'. Types of parameters 'context' and 'hook' are incompatible. Type 'HookContext<any, Service<any>>' is not assignable to type 'APIHookContext'. Types of property 'app' are incompatible. Type 'Application<{}>' is missing the following properties from type 'Application': request, response, init, defaultConfiguration, and 40 more.ts(2345)

I would like to have a consistent application object that is used inside hook methods, class methods etc... that has all of the services and their types and things such as a typed get object etc...

I have been able to achieve this in the declaration.d.ts file but the above conflicts and the reference to "this" are blocking me.

Let me know what is possible and if there is a way to achieve this level of typing.

Regards

@robbyphillips
Copy link
Contributor

@robbyphillips robbyphillips commented May 27, 2020

For a better typed HookContext: #1742 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.