Skip to content

Commit 8ba9ac7

Browse files
authored
Fix support for index types in flow (#838)
1 parent fe162f7 commit 8ba9ac7

File tree

5 files changed

+99
-1
lines changed

5 files changed

+99
-1
lines changed

Diff for: .changeset/tender-rings-live.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'react-docgen': patch
3+
---
4+
5+
Support index types correctly in flow

Diff for: packages/react-docgen/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap

+14
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,20 @@ exports[`getFlowType > handles ObjectTypeSpreadProperty from imported types 1`]
134134
}
135135
`;
136136

137+
exports[`getFlowType > handles indexed access on alias 1`] = `
138+
{
139+
"name": "string",
140+
"raw": "A[\\"x\\"]",
141+
}
142+
`;
143+
144+
exports[`getFlowType > handles indexed access on interface 1`] = `
145+
{
146+
"name": "A[\\"x\\"]",
147+
"raw": "A[\\"x\\"]",
148+
}
149+
`;
150+
137151
exports[`getFlowType > handles nested ObjectTypeSpreadProperty 1`] = `
138152
{
139153
"name": "signature",

Diff for: packages/react-docgen/src/utils/__tests__/getFlowType-test.ts

+36
Original file line numberDiff line numberDiff line change
@@ -1686,4 +1686,40 @@ describe('getFlowType', () => {
16861686

16871687
expect(getFlowType(typePath)).toMatchSnapshot();
16881688
});
1689+
1690+
test('handles indexed access on interface', () => {
1691+
const typePath = (
1692+
parse
1693+
.statement<VariableDeclaration>(
1694+
`
1695+
var x: A["x"] = 2;
1696+
interface A { x: string };
1697+
`,
1698+
)
1699+
.get('declarations')[0]
1700+
.get('id') as NodePath<Identifier>
1701+
)
1702+
.get('typeAnnotation')
1703+
.get('typeAnnotation') as NodePath<FlowType>;
1704+
1705+
expect(getFlowType(typePath)).toMatchSnapshot();
1706+
});
1707+
1708+
test('handles indexed access on alias', () => {
1709+
const typePath = (
1710+
parse
1711+
.statement<VariableDeclaration>(
1712+
`
1713+
var x: A["x"] = 2;
1714+
type A = { x: string };
1715+
`,
1716+
)
1717+
.get('declarations')[0]
1718+
.get('id') as NodePath<Identifier>
1719+
)
1720+
.get('typeAnnotation')
1721+
.get('typeAnnotation') as NodePath<FlowType>;
1722+
1723+
expect(getFlowType(typePath)).toMatchSnapshot();
1724+
});
16891725
});

Diff for: packages/react-docgen/src/utils/getFlowType.ts

+41
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import getTypeParameters from '../utils/getTypeParameters.js';
88
import type {
99
ElementsType,
1010
FunctionSignatureType,
11+
LiteralType,
1112
ObjectSignatureType,
1213
SimpleType,
1314
TypeDescriptor,
@@ -20,6 +21,7 @@ import type {
2021
FunctionTypeAnnotation,
2122
GenericTypeAnnotation,
2223
Identifier,
24+
IndexedAccessType,
2325
InterfaceDeclaration,
2426
IntersectionTypeAnnotation,
2527
Node,
@@ -69,6 +71,7 @@ const namedTypes: Record<
6971
IntersectionTypeAnnotation: handleIntersectionTypeAnnotation,
7072
TupleTypeAnnotation: handleTupleTypeAnnotation,
7173
TypeofTypeAnnotation: handleTypeofTypeAnnotation,
74+
IndexedAccessType: handleIndexedAccessType,
7275
};
7376

7477
function getFlowTypeWithRequirements(
@@ -413,6 +416,44 @@ function handleTypeofTypeAnnotation(
413416
return getFlowTypeWithResolvedTypes(path.get('argument'), typeParams);
414417
}
415418

419+
function handleIndexedAccessType(
420+
path: NodePath<IndexedAccessType>,
421+
typeParams: TypeParameters | null,
422+
): SimpleType {
423+
const objectType = getFlowTypeWithResolvedTypes(
424+
path.get('objectType'),
425+
typeParams,
426+
) as ObjectSignatureType<FunctionSignatureType>;
427+
const indexType = getFlowTypeWithResolvedTypes(
428+
path.get('indexType'),
429+
typeParams,
430+
) as LiteralType;
431+
432+
// We only get the signature if the objectType is a type (vs interface)
433+
if (!objectType.signature) {
434+
return {
435+
name: `${objectType.name}[${
436+
indexType.value ? indexType.value.toString() : indexType.name
437+
}]`,
438+
raw: printValue(path),
439+
};
440+
}
441+
442+
const resolvedType = objectType.signature.properties.find((p) => {
443+
// indexType.value = "'foo'"
444+
return indexType.value && p.key === indexType.value.replace(/['"]+/g, '');
445+
});
446+
447+
if (!resolvedType) {
448+
return { name: 'unknown' };
449+
}
450+
451+
return {
452+
name: resolvedType.value.name,
453+
raw: printValue(path),
454+
};
455+
}
456+
416457
let visitedTypes: Record<string, TypeDescriptor | boolean> = {};
417458

418459
function getFlowTypeWithResolvedTypes(

Diff for: packages/react-docgen/src/utils/getTSType.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,15 @@ function handleTSIndexedAccessType(
464464
) as LiteralType;
465465

466466
// We only get the signature if the objectType is a type (vs interface)
467-
if (!objectType.signature)
467+
if (!objectType.signature) {
468468
return {
469469
name: `${objectType.name}[${
470470
indexType.value ? indexType.value.toString() : indexType.name
471471
}]`,
472472
raw: printValue(path),
473473
};
474+
}
475+
474476
const resolvedType = objectType.signature.properties.find((p) => {
475477
// indexType.value = "'foo'"
476478
return indexType.value && p.key === indexType.value.replace(/['"]+/g, '');

0 commit comments

Comments
 (0)