inngest / inngest-js

The developer platform for easily building reliable workflows with zero infrastructure for TypeScript & JavaScript
https://www.inngest.com/
GNU General Public License v3.0
392 stars 40 forks source link

Mapped object type returns from `step.run()` are oversimplified #98

Closed jpwilliams closed 6 months ago

jpwilliams commented 1 year ago

Describe the bug

Mapped object types with property overrides lose those overrides when output from step.run().

This affects a user using the plaid/plaid-node package, where many of the types returned from client methods are these mapped object types with overrides.

It looks like this project uses OpenAPITools/openapi-generator to create these types, so it's likely that any project using that will suffer the same fate.

To Reproduce

// Create a mapped object type with overrides
interface Foo {
  [x: string]: any;
  foo: boolean;
}

// Within a step function, return the object type
const result = await step.run("Issue", () => undefined as unknown as Foo);

// Observe that `result` has lost the `foo: boolean;` property.

Expected behavior

The object type should be maintained.

System info (please complete the following information):

Additional context

The issue is caused because we use a Jsonify<> type from sindresorhus/type-fest to simulate the (de)serialization of data as it moves to/from Inngest, which is stripping the extra properties.

Need to investigate whether this is a conscious choice and, if not, whether the behaviour of the object type being maintained is reasonable.

JustinAimiable commented 11 months ago

👋 I wanted to see if there's been any progress or new info on this issue. In our codebase, we're exporting the handler callbacks that we pass into inngest.createFunction and testing them by passing a mock step object. This is a workaround to not being able to directly call the inngest functions that we create in order to unit test our handlers. One issue with this is the return types of step.run, which I've resorted to mocking like so:

run: (_name: string, cb: () => Promise<any>) => {
        return cb()
      }

Unfortunately, we lose type-safety on the return values from running a step this way. I tried using the built-in return type, but I think I'm running into the problem described in this issue when I do so. Any advice on how I can achieve type-safety and unit test my inngest functions? Thanks in advance :)

jpwilliams commented 6 months ago

@transitive-bullshit @JustinAimiable The fix for this is now shipped in v3.15.5. 🙂