Skip to content

Commit

Permalink
Fix support for index types in flow (#838)
Browse files Browse the repository at this point in the history
  • Loading branch information
danez committed Aug 30, 2023
1 parent fe162f7 commit 8ba9ac7
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/tender-rings-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-docgen': patch
---

Support index types correctly in flow
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ exports[`getFlowType > handles ObjectTypeSpreadProperty from imported types 1`]
}
`;

exports[`getFlowType > handles indexed access on alias 1`] = `
{
"name": "string",
"raw": "A[\\"x\\"]",
}
`;

exports[`getFlowType > handles indexed access on interface 1`] = `
{
"name": "A[\\"x\\"]",
"raw": "A[\\"x\\"]",
}
`;

exports[`getFlowType > handles nested ObjectTypeSpreadProperty 1`] = `
{
"name": "signature",
Expand Down
36 changes: 36 additions & 0 deletions packages/react-docgen/src/utils/__tests__/getFlowType-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1686,4 +1686,40 @@ describe('getFlowType', () => {

expect(getFlowType(typePath)).toMatchSnapshot();
});

test('handles indexed access on interface', () => {
const typePath = (
parse
.statement<VariableDeclaration>(
`
var x: A["x"] = 2;
interface A { x: string };
`,
)
.get('declarations')[0]
.get('id') as NodePath<Identifier>
)
.get('typeAnnotation')
.get('typeAnnotation') as NodePath<FlowType>;

expect(getFlowType(typePath)).toMatchSnapshot();
});

test('handles indexed access on alias', () => {
const typePath = (
parse
.statement<VariableDeclaration>(
`
var x: A["x"] = 2;
type A = { x: string };
`,
)
.get('declarations')[0]
.get('id') as NodePath<Identifier>
)
.get('typeAnnotation')
.get('typeAnnotation') as NodePath<FlowType>;

expect(getFlowType(typePath)).toMatchSnapshot();
});
});
41 changes: 41 additions & 0 deletions packages/react-docgen/src/utils/getFlowType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import getTypeParameters from '../utils/getTypeParameters.js';
import type {
ElementsType,
FunctionSignatureType,
LiteralType,
ObjectSignatureType,
SimpleType,
TypeDescriptor,
Expand All @@ -20,6 +21,7 @@ import type {
FunctionTypeAnnotation,
GenericTypeAnnotation,
Identifier,
IndexedAccessType,
InterfaceDeclaration,
IntersectionTypeAnnotation,
Node,
Expand Down Expand Up @@ -69,6 +71,7 @@ const namedTypes: Record<
IntersectionTypeAnnotation: handleIntersectionTypeAnnotation,
TupleTypeAnnotation: handleTupleTypeAnnotation,
TypeofTypeAnnotation: handleTypeofTypeAnnotation,
IndexedAccessType: handleIndexedAccessType,
};

function getFlowTypeWithRequirements(
Expand Down Expand Up @@ -413,6 +416,44 @@ function handleTypeofTypeAnnotation(
return getFlowTypeWithResolvedTypes(path.get('argument'), typeParams);
}

function handleIndexedAccessType(
path: NodePath<IndexedAccessType>,
typeParams: TypeParameters | null,
): SimpleType {
const objectType = getFlowTypeWithResolvedTypes(
path.get('objectType'),
typeParams,
) as ObjectSignatureType<FunctionSignatureType>;
const indexType = getFlowTypeWithResolvedTypes(
path.get('indexType'),
typeParams,
) as LiteralType;

// We only get the signature if the objectType is a type (vs interface)
if (!objectType.signature) {
return {
name: `${objectType.name}[${
indexType.value ? indexType.value.toString() : indexType.name
}]`,
raw: printValue(path),
};
}

const resolvedType = objectType.signature.properties.find((p) => {
// indexType.value = "'foo'"
return indexType.value && p.key === indexType.value.replace(/['"]+/g, '');
});

if (!resolvedType) {
return { name: 'unknown' };
}

return {
name: resolvedType.value.name,
raw: printValue(path),
};
}

let visitedTypes: Record<string, TypeDescriptor | boolean> = {};

function getFlowTypeWithResolvedTypes(
Expand Down
4 changes: 3 additions & 1 deletion packages/react-docgen/src/utils/getTSType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,13 +464,15 @@ function handleTSIndexedAccessType(
) as LiteralType;

// We only get the signature if the objectType is a type (vs interface)
if (!objectType.signature)
if (!objectType.signature) {
return {
name: `${objectType.name}[${
indexType.value ? indexType.value.toString() : indexType.name
}]`,
raw: printValue(path),
};
}

const resolvedType = objectType.signature.properties.find((p) => {
// indexType.value = "'foo'"
return indexType.value && p.key === indexType.value.replace(/['"]+/g, '');
Expand Down

0 comments on commit 8ba9ac7

Please sign in to comment.