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

Typings of instrument function in @storybook/instrumenter are incorrect #17925

Closed
bilalq opened this issue Apr 10, 2022 · 2 comments
Closed

Typings of instrument function in @storybook/instrumenter are incorrect #17925

bilalq opened this issue Apr 10, 2022 · 2 comments

Comments

@bilalq
Copy link

bilalq commented Apr 10, 2022

Describe the bug
The instrument function currently claims to return the same type as it receives. However, that's not the case when intercept is set to true and a Promise is returned instead.

This causes issues when trying to await things like userEvent.click(...) in @storybook/testing-library, as reported in storybookjs/testing-library#10.

I believe the typings here could be improved by defining a recursive conditional type. That would look something like this:

/**
 * A utility type that transforms a function type into one that returns a
 * Promise type of the existing value type.
 */
type PromisifiedReturn<T extends (...args: any) => any> =
  ReturnType<T> extends PromiseLike<unknown>
    ? T
    : (...a: Parameters<T>) => Promise<ReturnType<T>>

/**
 * A recursive utility type that transforms all functions types nested within
 * the object to return Promises instead of their existing value types.
 */
type InstrumentedObject<T> = {
  [K in keyof T]: 
    // If the value is a function, we transform its type to be one that returns a Promise
    T[K] extends (...args: any) => any 
    ? PromisifiedReturn<T[K]>
    // If it's an Array, we recursively transform its elements' types
    : T[K] extends (infer U)[]
    ? InstrumentedObject<U>[]
    // If it's an Object, we recursively transform its properties' types
    : T[K] extends object
    ? InstrumentedObject<T[K]>
    // Otherwise, we just keep the type as it is
    : T[K]
}

You can explore the proposed solution at this TypeScript playground link and hover over the instrumented object's properties to see what there types look like after instrumentation.

Note that if the behavior should be that the return type should remain TObj if instrument is not set to true, that can be achieved by a discriminant function signature that returns a different type depending on the input.

To Reproduce

  1. Try to await userEvent.click(...) in a story and see linter warnings that you are awaiting a non-promise.
  2. To experiment with the proposed solution, see this TypeScript playground link.

System

  System:
    OS: macOS 12.0.1
    CPU: (10) arm64 Apple M1 Max
  Binaries:
    Node: 16.14.2 - ~/.n/bin/node
    npm: 8.5.0 - ~/.n/bin/npm
  Browsers:
    Chrome: 100.0.4896.75
    Firefox: 99.0
    Safari: 15.1
  npmPackages:
    @storybook/addon-actions: ^6.5.0-alpha.60 => 6.5.0-alpha.60
    @storybook/addon-essentials: ^6.5.0-alpha.60 => 6.5.0-alpha.60
    @storybook/addon-interactions: ^6.5.0-alpha.60 => 6.5.0-alpha.60
    @storybook/addon-links: ^6.5.0-alpha.60 => 6.5.0-alpha.60
    @storybook/addons: ^6.4.21 => 6.4.21
    @storybook/builder-vite: ^0.1.26 => 0.1.26
    @storybook/react: ^6.5.0-alpha.60 => 6.5.0-alpha.60
    @storybook/testing-library: ^0.0.9 => 0.0.9
    @storybook/theming: ^6.4.21 => 6.4.21

Additional context
N/A

@shilman
Copy link
Member

shilman commented Jun 8, 2023

We’re cleaning house! Storybook has changed a lot since this issue was created and we don’t know if it’s still valid. Please open a new issue referencing this one if:

@shilman shilman closed this as not planned Won't fix, can't repro, duplicate, stale Jun 8, 2023
@kasperpeulen
Copy link
Contributor

We fixed part of this in
storybookjs/jest#34
and other parts of this in
storybookjs/testing-library#43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

3 participants