Skip to content

Commit 0b170af

Browse files
authored
fix: Use symbol type when there's no baseconstraint (#23)
1 parent 2ac9140 commit 0b170af

File tree

5 files changed

+95
-4
lines changed

5 files changed

+95
-4
lines changed

src/parser.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,21 @@ export function parseFromProgram(
376376
}
377377
}
378378

379-
let type = declaration
379+
const symbolType = declaration
380380
? // The proptypes aren't detailed enough that we need all the different combinations
381381
// so we just pick the first and ignore the rest
382-
checker.getTypeAtLocation(declaration)
382+
checker.getTypeOfSymbolAtLocation(symbol, declaration)
383383
: // The properties of Record<..., ...> don't have a declaration, but the symbol has a type property
384384
((symbol as any).type as ts.Type);
385385
// get `React.ElementType` from `C extends React.ElementType`
386-
const baseConstraintOfType = checker.getBaseConstraintOfType(type);
387-
type = baseConstraintOfType === undefined ? type : baseConstraintOfType;
386+
const declaredType =
387+
declaration !== undefined ? checker.getTypeAtLocation(declaration) : undefined;
388+
const baseConstraintOfType =
389+
declaredType !== undefined ? checker.getBaseConstraintOfType(declaredType) : undefined;
390+
const type =
391+
baseConstraintOfType !== undefined && baseConstraintOfType !== declaredType
392+
? baseConstraintOfType
393+
: symbolType;
388394

389395
if (!type) {
390396
throw new Error('No types found');

test/union-props/input.d.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'react';
2+
3+
export interface BaseProps {
4+
value?: unknown;
5+
}
6+
7+
export interface StandardProps extends BaseProps {
8+
variant?: 'standard';
9+
}
10+
11+
export interface OutlinedProps extends BaseProps {
12+
variant: 'outlined';
13+
}
14+
15+
export interface FilledProps extends BaseProps {
16+
variant: 'filled';
17+
}
18+
19+
export type TextFieldProps = StandardProps | OutlinedProps | FilledProps;
20+
21+
export default function TextField(props: TextFieldProps): JSX.Element;

test/union-props/input.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as React from 'react';
2+
3+
export default function TextField(props) {
4+
const { value, variant } = props;
5+
6+
return (
7+
<React.Fragment>
8+
{variant}: <input value={value} />
9+
</React.Fragment>
10+
);
11+
}

test/union-props/output.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
function TextField(props) {
5+
const { value, variant } = props;
6+
7+
return (
8+
<React.Fragment>
9+
{variant}: <input value={value} />
10+
</React.Fragment>
11+
);
12+
}
13+
14+
TextField.propTypes = {
15+
value: PropTypes.any,
16+
variant: PropTypes.oneOf(['filled', 'outlined', 'standard']),
17+
};
18+
19+
export default TextField;

test/union-props/output.json

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"type": "ProgramNode",
3+
"body": [
4+
{
5+
"type": "ComponentNode",
6+
"name": "TextField",
7+
"types": [
8+
{
9+
"type": "PropTypeNode",
10+
"name": "variant",
11+
"propType": {
12+
"type": "UnionNode",
13+
"types": [
14+
{ "type": "UndefinedNode" },
15+
{ "type": "LiteralNode", "value": "\"standard\"" },
16+
{ "type": "LiteralNode", "value": "\"outlined\"" },
17+
{ "type": "LiteralNode", "value": "\"filled\"" }
18+
]
19+
},
20+
"filenames": {}
21+
},
22+
{
23+
"type": "PropTypeNode",
24+
"name": "value",
25+
"propType": {
26+
"type": "UnionNode",
27+
"types": [{ "type": "UndefinedNode" }, { "type": "AnyNode" }]
28+
},
29+
"filenames": {}
30+
}
31+
]
32+
}
33+
]
34+
}

0 commit comments

Comments
 (0)