Summary
react-docgen-typescript@2.4.0 crashes with TypeError: Cannot read properties of undefined (reading 'parameters') when parsing callable types that have @public tagged properties that are not callable (e.g., displayName).
Reproduction
https://codesandbox.io/p/devbox/wdz724
pnpm install
node test.js
Expected Behavior
The parser should gracefully handle callable types that have non-callable @public members, either by:
- Skipping members that have no call signature
- Treating them as properties instead of methods
Actual Behavior
TypeError: Cannot read properties of undefined (reading 'parameters')
at Parser.getParameterInfo (.../react-docgen-typescript/lib/parser.js:400:30)
at Parser.getMethodsInfo (.../react-docgen-typescript/lib/parser.js:365:32)
at Parser.getComponentInfo (.../react-docgen-typescript/lib/parser.js:254:28)
Root Cause
In parser.js, the getMethodsInfo function:
- Calls
isTaggedPublic(member) which returns true for displayName (line 563)
- Calls
getCallSignature(member) which returns undefined because displayName has no call signature (line 569)
- Calls
getParameterInfo(callSignature) which tries to access callSignature.parameters but callSignature is undefined (line 570)
|
public getMethodsInfo(type: ts.Type): Method[] { |
|
const members = this.extractMembersFromType(type); |
|
const methods: Method[] = []; |
|
members.forEach(member => { |
|
if (!this.isTaggedPublic(member)) { |
|
return; |
|
} |
|
|
|
const name = member.getName(); |
|
const docblock = this.getFullJsDocComment(member).fullComment; |
|
const callSignature = this.getCallSignature(member); |
|
const params = this.getParameterInfo(callSignature); |
|
const description = ts.displayPartsToString( |
public getMethodsInfo(type: ts.Type): Method[] {
const members = this.extractMembersFromType(type);
const methods: Method[] = [];
members.forEach(member => {
if (!this.isTaggedPublic(member)) {
return;
}
const name = member.getName();
const docblock = this.getFullJsDocComment(member).fullComment;
const callSignature = this.getCallSignature(member); // Returns undefined!
const params = this.getParameterInfo(callSignature); // Crashes here
//...
});
return methods;
}
Trigger Condition
The bug is triggered when:
- A component is a callable type (has a call signature)
- The type also has members (properties or methods on
type.symbol.members)
- One of those members is tagged with
@public in JSDoc
- That member does NOT have a call signature (it's a property, not a method)
This pattern is common in libraries like framer-motion where components like AnimatePresence are callable types with a displayName property.
Minimal Reproduction Code
// Component.tsx
import React from 'react';
interface AnimatePresenceProps {
children: React.ReactNode;
}
interface AnimatePresenceType {
(props: React.PropsWithChildren<AnimatePresenceProps>): JSX.Element | null;
/**
* @public <-- This is the problematic tag
*/
displayName?: string;
}
/**
* @public
*/
export const WrappedAnimator: AnimatePresenceType = Object.assign(
(props: React.PropsWithChildren<AnimatePresenceProps>) => {
return <div>{props.children}</div>;
},
{
/**
* @public
*/
displayName: 'WrappedAnimator' as string | undefined,
}
);
Suggested Fix
Add a guard in getMethodsInfo to skip members that have no call signature:
public getMethodsInfo(type: ts.Type): Method[] {
const members = this.extractMembersFromType(type);
const methods: Method[] = [];
members.forEach(member => {
if (!this.isTaggedPublic(member)) {
return;
}
const callSignature = this.getCallSignature(member);
// Skip members that are not callable (properties, not methods)
if (!callSignature) {
return;
}
// ... rest of the function
});
return methods;
}
Affected Version
react-docgen-typescript@2.4.0
- Tested with
typescript@5.9.3
Context
This bug was discovered while using Storybook 9.x with framer-motion. The AnimatePresence component from framer-motion has this exact type structure, causing Storybook builds to fail.
Workaround
In Storybook's main.js, switch to using react-docgen instead of react-docgen-typescript:
typescript: {
reactDocgen: 'react-docgen', // Use 'react-docgen' instead of 'react-docgen-typescript'
},
Summary
react-docgen-typescript@2.4.0crashes withTypeError: Cannot read properties of undefined (reading 'parameters')when parsing callable types that have@publictagged properties that are not callable (e.g.,displayName).Reproduction
https://codesandbox.io/p/devbox/wdz724
Expected Behavior
The parser should gracefully handle callable types that have non-callable
@publicmembers, either by:Actual Behavior
Root Cause
In
parser.js, thegetMethodsInfofunction:isTaggedPublic(member)which returnstruefordisplayName(line 563)getCallSignature(member)which returnsundefinedbecausedisplayNamehas no call signature (line 569)getParameterInfo(callSignature)which tries to accesscallSignature.parametersbutcallSignatureisundefined(line 570)react-docgen-typescript/src/parser.ts
Lines 559 to 571 in e1f8f5f
Trigger Condition
The bug is triggered when:
type.symbol.members)@publicin JSDocThis pattern is common in libraries like
framer-motionwhere components likeAnimatePresenceare callable types with adisplayNameproperty.Minimal Reproduction Code
Suggested Fix
Add a guard in
getMethodsInfoto skip members that have no call signature:Affected Version
react-docgen-typescript@2.4.0typescript@5.9.3Context
This bug was discovered while using Storybook 9.x with
framer-motion. TheAnimatePresencecomponent from framer-motion has this exact type structure, causing Storybook builds to fail.Workaround
In Storybook's
main.js, switch to usingreact-docgeninstead ofreact-docgen-typescript: