Skip to content

Adding type validation to job arguments #430

@jamesgecko

Description

@jamesgecko

Problem

It seems like it's pretty difficult to add types to job arguments. Assigning an interface to the arguments of a job appears to always trigger a TypeScript validation error. If I try to do something like this:

interface MyArgs {
  id: string;
  url: string;
  resources: Record<string, string>[];
}

const jobFn: JobFunction = (args: MyArgs) => async (ctx: MyContext) => {
  // ...
}
faktory.register('MyJob', jobFn);

It results in a build error like this

src/worker/jobs/my-job.ts:50:7 - error TS2322: Type '(args: SwapArgs) => (ctx: MyContext) => Promise<void>' is not assignable to type 'JobFunction'.
  Type '(args: MyArgs) => (ctx: MyContext) => Promise<void>' is not assignable to type 'JobFunctionContextWrapper'.
    Types of parameters 'args' and 'args' are incompatible.
      Type 'unknown' is not assignable to type 'MyArgs'.

50 const jobFn: JobFunction = (args: MyArgs) => async (ctx: MyContext) => {
         ~~~~~~

Workaround 1: Force the custom type in the job function

I can halfway work around this by leaving the args untyped and forcing them in the function. But then TypeScript doesn't help me if I try to queue a job with arguments that don't match the type.

const jobFn: JobFunction = (args) => async (ctx: MyContext) => {
    const typed = args as unknown as MyArgs;
    // ...
}

Workaround 2: Force the original type during registration

The other way I can work around this is by setting a semi-compatible type, but then forcing the original type during registration. This is the best solution I've found so far.

type TypedJobFunction<T> = (args: T) => (ctx: MyContext) => Promise<unknown>;

const jobFn: TypedJobFunction<MyArgs> = (args) => async (ctx) => {
    // ...
}

// ...
faktory.register("My Job", jobFn as JobFunction);

I still need to manually use the type when queuing a job. 😞

It seems like probably need some changes to the typings this library provides to make this seamless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions