diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js index 50e4e18aa4c2c6..e8668947ce28c1 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js @@ -644,6 +644,8 @@ export interface Spec extends TurboModule { +getCallback: () => () => void; +getMixed: (arg: mixed) => mixed; +getEnums: (quality: Quality, resolution?: Resolution, floppy: Floppy, stringOptions: StringOptions) => string; + +getMap: (arg: {[a: string]: ?number}) => {[b: string]: ?number}; + +getAnotherMap: (arg: {[string]: string}) => {[string]: string}; +getUnion: (chooseInt: ChooseInt, chooseFloat: ChooseFloat, chooseObject: ChooseObject, chooseString: ChooseString) => ChooseObject; } diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index e73868dc872a3c..c3718298981715 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -122,6 +122,86 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`] ] } }, + { + 'name': 'getMap', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'b', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + } + } + ] + } + }, + { + 'name': 'getAnotherMap', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'key', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'key', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + ] + } + }, { 'name': 'getUnion', 'optional': false, diff --git a/packages/react-native-codegen/src/parsers/flow/modules/index.js b/packages/react-native-codegen/src/parsers/flow/modules/index.js index 8cfd853d4fcbb2..21e72cf77ef580 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/index.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/index.js @@ -62,7 +62,6 @@ const { UnsupportedTypeAnnotationParserError, UnsupportedFunctionParamTypeAnnotationParserError, UnsupportedEnumDeclarationParserError, - UnsupportedUnionTypeAnnotationParserError, UnsupportedObjectPropertyTypeAnnotationParserError, IncorrectModuleRegistryCallArgumentTypeParserError, } = require('../../errors.js'); @@ -83,6 +82,7 @@ const { } = require('../../error-utils'); const {FlowParser} = require('../parser.js'); +import {getKeyName} from '../../parsers-commons'; const language = 'Flow'; const parser = new FlowParser(); @@ -288,11 +288,17 @@ function translateTypeAnnotation( const objectTypeAnnotation = { type: 'ObjectTypeAnnotation', // $FlowFixMe[missing-type-arg] - properties: (typeAnnotation.properties: Array<$FlowFixMe>) + properties: ([ + ...typeAnnotation.properties, + ...typeAnnotation.indexers, + ]: Array<$FlowFixMe>) .map>>( property => { return tryParse(() => { - if (property.type !== 'ObjectTypeProperty') { + if ( + property.type !== 'ObjectTypeProperty' && + property.type !== 'ObjectTypeIndexer' + ) { throw new UnsupportedObjectPropertyTypeAnnotationParserError( hasteModuleName, property, @@ -301,7 +307,8 @@ function translateTypeAnnotation( ); } - const {optional, key} = property; + const {optional = false} = property; + const name = getKeyName(property, hasteModuleName, language); const [propertyTypeAnnotation, isPropertyNullable] = unwrapNullable( @@ -329,7 +336,7 @@ function translateTypeAnnotation( ); } else { return { - name: key.name, + name, optional, typeAnnotation: wrapNullable( isPropertyNullable, diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index eda3b3ef2990d3..1528399b066608 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -24,7 +24,9 @@ const { UnsupportedUnionTypeAnnotationParserError, } = require('./errors'); import type {ParserType} from './errors'; - +const { + UnsupportedObjectPropertyTypeAnnotationParserError, +} = require('./errors'); const invariant = require('invariant'); function wrapModuleSchema( @@ -155,6 +157,31 @@ function emitUnionTypeAnnotation( }); } +function getKeyName( + propertyOrIndex: $FlowFixMe, + hasteModuleName: string, + language: ParserType, +): string { + switch (propertyOrIndex.type) { + case 'ObjectTypeProperty': + case 'TSPropertySignature': + return propertyOrIndex.key.name; + case 'ObjectTypeIndexer': + // flow index name is optional + return propertyOrIndex.id?.name ?? 'key'; + case 'TSIndexSignature': + // TypeScript index name is mandatory + return propertyOrIndex.parameters[0].name; + default: + throw new UnsupportedObjectPropertyTypeAnnotationParserError( + hasteModuleName, + propertyOrIndex, + propertyOrIndex.type, + language, + ); + } +} + module.exports = { wrapModuleSchema, unwrapNullable, @@ -162,4 +189,5 @@ module.exports = { assertGenericTypeAnnotationHasExactlyOneTypeParameter, emitMixedTypeAnnotation, emitUnionTypeAnnotation, + getKeyName, }; diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js index 02a2ae68b98a14..83483075d5ba49 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js @@ -661,6 +661,8 @@ export interface Spec extends TurboModule { readonly getCallback: () => () => void; readonly getMixed: (arg: unknown) => unknown; readonly getEnums: (quality: Quality, resolution?: Resolution, floppy: Floppy, stringOptions: StringOptions) => string; + readonly getMap: (arg: {[a: string]: number | null;}) => {[b: string]: number | null;}; + readonly getAnotherMap: (arg: {[key: string]: string}) => {[key: string]: string}; readonly getUnion: (chooseInt: ChooseInt, chooseFloat: ChooseFloat, chooseObject: ChooseObject, chooseString: ChooseString) => ChooseObject; } diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 6b4ff88450528a..3526a8245b1818 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -120,6 +120,86 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL ] } }, + { + 'name': 'getMap', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'b', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + } + } + ] + } + }, + { + 'name': 'getAnotherMap', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'key', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'key', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + ] + } + }, { 'name': 'getUnion', 'optional': false, diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/index.js b/packages/react-native-codegen/src/parsers/typescript/modules/index.js index 9c6f6080faa54e..590c938e40a796 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/index.js @@ -81,6 +81,7 @@ const { } = require('../../error-utils'); const {TypeScriptParser} = require('../parser'); +import {getKeyName} from '../../parsers-commons'; const language = 'TypeScript'; const parser = new TypeScriptParser(); @@ -305,7 +306,10 @@ function translateTypeAnnotation( .map>>( property => { return tryParse(() => { - if (property.type !== 'TSPropertySignature') { + if ( + property.type !== 'TSPropertySignature' && + property.type !== 'TSIndexSignature' + ) { throw new UnsupportedObjectPropertyTypeAnnotationParserError( hasteModuleName, property, @@ -314,7 +318,8 @@ function translateTypeAnnotation( ); } - const {optional = false, key} = property; + const {optional = false} = property; + const name = getKeyName(property, hasteModuleName, language); const [propertyTypeAnnotation, isPropertyNullable] = unwrapNullable( @@ -342,7 +347,7 @@ function translateTypeAnnotation( ); } else { return { - name: key.name, + name, optional, typeAnnotation: wrapNullable( isPropertyNullable,