Merge pull request #19839 from storybookjs/kasper/fix-decorator

Fix type inference bug with decorators
This commit is contained in:
Kasper Peulen 2022-11-16 17:42:00 +01:00 committed by GitHub
commit 4cf0afe32c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 6 deletions

View File

@ -1,7 +1,7 @@
import { describe, test } from '@jest/globals';
import { satisfies } from '@storybook/core-common';
import type { StoryAnnotations } from '@storybook/types';
import type { Args, StoryAnnotations, StrictArgs } from '@storybook/types';
import { expectTypeOf } from 'expect-type';
import type { KeyboardEventHandler, ReactNode } from 'react';
import React from 'react';
@ -11,7 +11,7 @@ import type { SetOptional } from 'type-fest';
import type { Decorator, Meta, StoryObj } from './public-types';
import type { ReactRenderer } from './types';
type ReactStory<Args, RequiredArgs> = StoryAnnotations<ReactRenderer, Args, RequiredArgs>;
type ReactStory<TArgs, TRequiredArgs> = StoryAnnotations<ReactRenderer, TArgs, TRequiredArgs>;
type ButtonProps = { label: string; disabled: boolean };
const Button: (props: ButtonProps) => JSX.Element = () => <></>;
@ -172,10 +172,24 @@ describe('Story args can be inferred', () => {
</>
);
// decorator is not using args
const thirdDecorator: Decorator<Args> = (Story) => (
<>
<Story />
</>
);
// decorator is not using args
const fourthDecorator: Decorator<StrictArgs> = (Story) => (
<>
<Story />
</>
);
const meta = satisfies<Meta<Props>>()({
component: Button,
args: { disabled: false },
decorators: [withDecorator, secondDecorator],
decorators: [withDecorator, secondDecorator, thirdDecorator, fourthDecorator],
});
const Basic: StoryObj<typeof meta> = {

View File

@ -54,15 +54,22 @@ export type StoryObj<TMetaOrCmpOrArgs = Args> = TMetaOrCmpOrArgs extends {
? StoryAnnotations<
ReactRenderer,
TArgs,
SetOptional<TArgs, Extract<keyof TArgs, keyof (DefaultArgs & ActionArgs<TArgs>)>>
SetOptional<TArgs, keyof TArgs & keyof (DefaultArgs & ActionArgs<TArgs>)>
>
: never
: TMetaOrCmpOrArgs extends ComponentType<any>
? StoryAnnotations<ReactRenderer, ComponentProps<TMetaOrCmpOrArgs>>
: StoryAnnotations<ReactRenderer, TMetaOrCmpOrArgs>;
type ActionArgs<RArgs> = {
[P in keyof RArgs as ((...args: any[]) => void) extends RArgs[P] ? P : never]: RArgs[P];
type ActionArgs<TArgs> = {
// This can be read as: filter TArgs on functions where we can assign a void function to that function.
// The docs addon argsEnhancers can only safely provide a default value for void functions.
// Other kind of required functions should be provided by the user.
[P in keyof TArgs as TArgs[P] extends (...args: any[]) => any
? ((...args: any[]) => void) extends TArgs[P]
? P
: never
: never]: TArgs[P];
};
/**