diff --git a/src/utils/__tests__/getTSType-test.js b/src/utils/__tests__/getTSType-test.js index 2960b2bbb36..d543adf2b18 100644 --- a/src/utils/__tests__/getTSType-test.js +++ b/src/utils/__tests__/getTSType-test.js @@ -315,6 +315,38 @@ describe('getTSType', () => { }); }); + it('detects indexed access', () => { + const typePath = statement(` + var x: A["x"] = 2; + + interface A { x: string }; + `) + .get('declarations', 0) + .get('id') + .get('typeAnnotation') + .get('typeAnnotation'); + expect(getTSType(typePath)).toEqual({ + name: 'A["x"]', + raw: 'A["x"]', + }); + }); + + it('resolves indexed access', () => { + const typePath = statement(` + var x: A["x"] = 2; + + type A = { x: string }; + `) + .get('declarations', 0) + .get('id') + .get('typeAnnotation') + .get('typeAnnotation'); + expect(getTSType(typePath)).toEqual({ + name: 'string', + raw: 'A["x"]', + }); + }); + it('resolves types in scope', () => { const typePath = statement(` var x: MyType = 2; diff --git a/src/utils/getTSType.js b/src/utils/getTSType.js index 9671c3e1e36..65adc58e9bf 100644 --- a/src/utils/getTSType.js +++ b/src/utils/getTSType.js @@ -19,6 +19,7 @@ import getTypeParameters, { import type { FlowElementsType, FlowFunctionArgumentType, + FlowLiteralType, FlowObjectSignatureType, FlowSimpleType, FlowTypeDescriptor, @@ -54,6 +55,7 @@ const namedTypes = { TSTupleType: handleTSTupleType, TSTypeQuery: handleTSTypeQuery, TSTypeOperator: handleTSTypeOperator, + TSIndexedAccessType: handleTSIndexedAccessType, }; function handleTSArrayType( @@ -347,6 +349,40 @@ function handleTSTypeOperator(path: NodePath): ?FlowTypeDescriptor { } } +function handleTSIndexedAccessType( + path: NodePath, + typeParams: ?TypeParameters, +): FlowSimpleType { + // eslint-disable-next-line no-undef + const objectType: $Shape = getTSTypeWithResolvedTypes( + path.get('objectType'), + typeParams, + ); + // eslint-disable-next-line no-undef + const indexType: $Shape = getTSTypeWithResolvedTypes( + path.get('indexType'), + typeParams, + ); + + // We only get the signature if the objectType is a type (vs interface) + if (!objectType.signature) + return { + name: `${objectType.name}[${indexType.value.toString()}]`, + raw: printValue(path), + }; + const resolvedType = objectType.signature.properties.find(p => { + // indexType.value = "'foo'" + return p.key === indexType.value.replace(/['"]+/g, ''); + }); + if (!resolvedType) { + return { name: 'unknown' }; + } + return { + name: resolvedType.value.name, + raw: printValue(path), + }; +} + let visitedTypes = {}; function getTSTypeWithResolvedTypes(