diff --git a/src/parser.ts b/src/parser.ts
index 772857a..d21322e 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -376,15 +376,21 @@ export function parseFromProgram(
}
}
- let type = declaration
+ const symbolType = declaration
? // The proptypes aren't detailed enough that we need all the different combinations
// so we just pick the first and ignore the rest
- checker.getTypeAtLocation(declaration)
+ checker.getTypeOfSymbolAtLocation(symbol, declaration)
: // The properties of Record<..., ...> don't have a declaration, but the symbol has a type property
((symbol as any).type as ts.Type);
// get `React.ElementType` from `C extends React.ElementType`
- const baseConstraintOfType = checker.getBaseConstraintOfType(type);
- type = baseConstraintOfType === undefined ? type : baseConstraintOfType;
+ const declaredType =
+ declaration !== undefined ? checker.getTypeAtLocation(declaration) : undefined;
+ const baseConstraintOfType =
+ declaredType !== undefined ? checker.getBaseConstraintOfType(declaredType) : undefined;
+ const type =
+ baseConstraintOfType !== undefined && baseConstraintOfType !== declaredType
+ ? baseConstraintOfType
+ : symbolType;
if (!type) {
throw new Error('No types found');
diff --git a/test/union-props/input.d.ts b/test/union-props/input.d.ts
new file mode 100644
index 0000000..05c56d1
--- /dev/null
+++ b/test/union-props/input.d.ts
@@ -0,0 +1,21 @@
+import * as React from 'react';
+
+export interface BaseProps {
+ value?: unknown;
+}
+
+export interface StandardProps extends BaseProps {
+ variant?: 'standard';
+}
+
+export interface OutlinedProps extends BaseProps {
+ variant: 'outlined';
+}
+
+export interface FilledProps extends BaseProps {
+ variant: 'filled';
+}
+
+export type TextFieldProps = StandardProps | OutlinedProps | FilledProps;
+
+export default function TextField(props: TextFieldProps): JSX.Element;
diff --git a/test/union-props/input.js b/test/union-props/input.js
new file mode 100644
index 0000000..65c2d58
--- /dev/null
+++ b/test/union-props/input.js
@@ -0,0 +1,11 @@
+import * as React from 'react';
+
+export default function TextField(props) {
+ const { value, variant } = props;
+
+ return (
+
+ {variant}:
+
+ );
+}
diff --git a/test/union-props/output.js b/test/union-props/output.js
new file mode 100644
index 0000000..77872fa
--- /dev/null
+++ b/test/union-props/output.js
@@ -0,0 +1,19 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+
+function TextField(props) {
+ const { value, variant } = props;
+
+ return (
+
+ {variant}:
+
+ );
+}
+
+TextField.propTypes = {
+ value: PropTypes.any,
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard']),
+};
+
+export default TextField;
diff --git a/test/union-props/output.json b/test/union-props/output.json
new file mode 100644
index 0000000..cc3e480
--- /dev/null
+++ b/test/union-props/output.json
@@ -0,0 +1,34 @@
+{
+ "type": "ProgramNode",
+ "body": [
+ {
+ "type": "ComponentNode",
+ "name": "TextField",
+ "types": [
+ {
+ "type": "PropTypeNode",
+ "name": "variant",
+ "propType": {
+ "type": "UnionNode",
+ "types": [
+ { "type": "UndefinedNode" },
+ { "type": "LiteralNode", "value": "\"standard\"" },
+ { "type": "LiteralNode", "value": "\"outlined\"" },
+ { "type": "LiteralNode", "value": "\"filled\"" }
+ ]
+ },
+ "filenames": {}
+ },
+ {
+ "type": "PropTypeNode",
+ "name": "value",
+ "propType": {
+ "type": "UnionNode",
+ "types": [{ "type": "UndefinedNode" }, { "type": "AnyNode" }]
+ },
+ "filenames": {}
+ }
+ ]
+ }
+ ]
+}