diff --git a/code/core/src/csf-tools/ConfigFile.test.ts b/code/core/src/csf-tools/ConfigFile.test.ts index f702579aeecd..191989b1751b 100644 --- a/code/core/src/csf-tools/ConfigFile.test.ts +++ b/code/core/src/csf-tools/ConfigFile.test.ts @@ -293,6 +293,23 @@ describe('ConfigFile', () => { ) ).toEqual(['test', 'vitest', '!a11ytest']); }); + it('parses correctly with .type() chaining on export default', () => { + const source = dedent` + import { definePreview } from '@storybook/react-vite'; + + export default definePreview({ + parameters: { + foo: 'bar', + }, + }).type<{ + parameters: { + customParam?: string; + }; + }>(); + `; + const config = loadConfig(source).parse(); + expect(config.getFieldValue(['parameters', 'foo'])).toEqual('bar'); + }); }); }); diff --git a/code/core/src/csf-tools/ConfigFile.ts b/code/core/src/csf-tools/ConfigFile.ts index c5f376f5096f..6e326004c82d 100644 --- a/code/core/src/csf-tools/ConfigFile.ts +++ b/code/core/src/csf-tools/ConfigFile.ts @@ -204,9 +204,19 @@ export class ConfigFile { self.hasDefaultExport = true; let decl = self._resolveDeclaration(node.declaration as t.Node, parent); - // csf factory - if (t.isCallExpression(decl) && t.isObjectExpression(decl.arguments[0])) { - decl = decl.arguments[0]; + // csf factory - unwrap call expressions like definePreview({...}) or definePreview({...}).type() + while (t.isCallExpression(decl)) { + if (t.isObjectExpression(decl.arguments[0])) { + decl = decl.arguments[0]; + break; + } else if ( + t.isMemberExpression(decl.callee) && + t.isCallExpression(decl.callee.object) + ) { + decl = decl.callee.object; + } else { + break; + } } if (t.isObjectExpression(decl)) {