diff --git a/packages/react-native-codegen/src/parsers/components/commands-commons.js b/packages/react-native-codegen/src/parsers/components/commands-commons.js new file mode 100644 index 000000000000..4290d9712003 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/components/commands-commons.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {ComponentCommandArrayTypeAnnotation} from '../../CodegenSchema.js'; +import type {Parser} from '../parser'; + +type Allowed = ComponentCommandArrayTypeAnnotation['elementType']; + +/** + * Shared command array element type resolution for Flow and TypeScript parsers. + * + * Uses parser.extractTypeFromTypeAnnotation() to resolve generic/reference types + * and parser.convertKeywordToTypeAnnotation() to normalize language-specific keywords + * to a common set of type names. + */ +function getCommandArrayElementTypeType( + inputType: unknown, + parser: Parser, +): Allowed { + // TODO: T172453752 support more complex type annotation for array element + if (inputType == null || typeof inputType !== 'object') { + throw new Error(`Expected an object, received ${typeof inputType}`); + } + + const rawType = inputType?.type; + if (typeof rawType !== 'string') { + throw new Error('Command array element type must be a string'); + } + + // $FlowFixMe[incompatible-call] + const resolvedName = parser.extractTypeFromTypeAnnotation(inputType); + const normalizedType = parser.convertKeywordToTypeAnnotation(resolvedName); + + switch (normalizedType) { + case 'BooleanTypeAnnotation': + return { + type: 'BooleanTypeAnnotation', + }; + case 'StringTypeAnnotation': + return { + type: 'StringTypeAnnotation', + }; + case 'Int32': + return { + type: 'Int32TypeAnnotation', + }; + case 'Float': + return { + type: 'FloatTypeAnnotation', + }; + case 'Double': + return { + type: 'DoubleTypeAnnotation', + }; + default: + // Unresolvable types (aliases to objects/unions) fall back to + // MixedTypeAnnotation. Generators produce ReadableMap or + // (const NSArray *) which are untyped. + return { + type: 'MixedTypeAnnotation', + }; + } +} + +module.exports = { + getCommandArrayElementTypeType, +}; diff --git a/packages/react-native-codegen/src/parsers/components/events-commons.js b/packages/react-native-codegen/src/parsers/components/events-commons.js new file mode 100644 index 000000000000..7a06ee4652c0 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/components/events-commons.js @@ -0,0 +1,217 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {EventTypeAnnotation, NamedShape} from '../../CodegenSchema.js'; +import type {Parser} from '../parser'; + +const {buildPropertiesForEvent} = require('../parsers-commons'); +const { + emitBoolProp, + emitDoubleProp, + emitFloatProp, + emitInt32Prop, + emitMixedProp, + emitObjectProp, + emitStringProp, + emitUnionProp, +} = require('../parsers-primitives'); + +/** + * Shared event property type resolution for Flow and TypeScript parsers. + * + * Both parsers resolve type annotations to normalized names using: + * - parser.extractTypeFromTypeAnnotation() to resolve generic/reference types + * - parser.convertKeywordToTypeAnnotation() to normalize language-specific keywords + * + * Flow-specific types ($ReadOnly, $ReadOnlyArray) are handled inline since + * TypeScript's parseTopLevelType() resolves them before this function is called. + */ +// Check if a type annotation represents null, undefined, or void. +// Covers both Flow (NullLiteralTypeAnnotation, VoidTypeAnnotation) and +// TypeScript (TSNullKeyword, TSUndefinedKeyword, TSVoidKeyword) AST nodes. +function isNullOrVoidType(typeAnnotation: $FlowFixMe): boolean { + return ( + typeAnnotation.type === 'NullLiteralTypeAnnotation' || + typeAnnotation.type === 'VoidTypeAnnotation' || + typeAnnotation.type === 'TSNullKeyword' || + typeAnnotation.type === 'TSUndefinedKeyword' || + typeAnnotation.type === 'TSVoidKeyword' + ); +} + +function getPropertyType( + name: string, + optional: boolean, + typeAnnotation: $FlowFixMe, + parser: Parser, +): NamedShape { + const resolvedType = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = parser.convertKeywordToTypeAnnotation(resolvedType); + + // Handle Flow's read-only wrappers (no-op for TS which pre-resolves these) + if (resolvedType === '$ReadOnly' || resolvedType === 'Readonly') { + return getPropertyType( + name, + optional, + typeAnnotation.typeParameters.params[0], + parser, + ); + } + + if (resolvedType === '$ReadOnlyArray' || resolvedType === 'ReadonlyArray') { + return { + name, + optional, + typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), + }; + } + + // For nullable unions (e.g. 'small' | 'large' | null | undefined), + // strip null/undefined/void types and unwrap single-type unions. + // TypeScript's parseTopLevelType handles this at the top level, but + // nested event properties also need this unwrapping. + if (type === 'UnionTypeAnnotation') { + const nonNullableTypes = typeAnnotation.types.filter( + (t: $FlowFixMe) => !isNullOrVoidType(t), + ); + if (nonNullableTypes.length < typeAnnotation.types.length) { + // Had nullable types - unwrap + if (nonNullableTypes.length === 1) { + return getPropertyType(name, true, nonNullableTypes[0], parser); + } + return emitUnionProp(name, true, parser, { + ...typeAnnotation, + types: nonNullableTypes, + }); + } + } + + switch (type) { + case 'BooleanTypeAnnotation': + return emitBoolProp(name, optional); + case 'StringTypeAnnotation': + return emitStringProp(name, optional); + case 'Int32': + return emitInt32Prop(name, optional); + case 'Double': + return emitDoubleProp(name, optional); + case 'Float': + return emitFloatProp(name, optional); + case 'ObjectTypeAnnotation': + return emitObjectProp( + name, + optional, + parser, + typeAnnotation, + extractArrayElementType, + ); + case 'UnionTypeAnnotation': + return emitUnionProp(name, optional, parser, typeAnnotation); + case 'UnsafeMixed': + return emitMixedProp(name, optional); + case 'ArrayTypeAnnotation': + return { + name, + optional, + typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), + }; + default: + throw new Error(`Unable to determine event type for "${name}": ${type}`); + } +} + +function extractArrayElementType( + typeAnnotation: $FlowFixMe, + name: string, + parser: Parser, +): EventTypeAnnotation { + const resolvedType = parser.extractTypeFromTypeAnnotation(typeAnnotation); + const type = parser.convertKeywordToTypeAnnotation(resolvedType); + + // Handle TS parenthesized types (no-op for Flow) + if (typeAnnotation.type === 'TSParenthesizedType') { + return extractArrayElementType(typeAnnotation.typeAnnotation, name, parser); + } + + // Handle Flow's read-only arrays (no-op for TS which pre-resolves these) + if (resolvedType === '$ReadOnlyArray' || resolvedType === 'ReadonlyArray') { + const genericParams = typeAnnotation.typeParameters.params; + if (genericParams.length !== 1) { + throw new Error( + `Events only supports arrays with 1 Generic type. Found ${ + genericParams.length + } types:\n${JSON.stringify(genericParams, null, 2)}`, + ); + } + return { + type: 'ArrayTypeAnnotation', + elementType: extractArrayElementType(genericParams[0], name, parser), + }; + } + + switch (type) { + case 'BooleanTypeAnnotation': + return {type: 'BooleanTypeAnnotation'}; + case 'StringTypeAnnotation': + return {type: 'StringTypeAnnotation'}; + case 'Int32': + return {type: 'Int32TypeAnnotation'}; + case 'Float': + return {type: 'FloatTypeAnnotation'}; + case 'NumberTypeAnnotation': + case 'Double': + return { + type: 'DoubleTypeAnnotation', + }; + case 'UnionTypeAnnotation': + return { + type: 'UnionTypeAnnotation', + types: typeAnnotation.types.map(option => ({ + type: 'StringLiteralTypeAnnotation', + value: parser.getLiteralValue(option), + })), + }; + case 'UnsafeMixed': + return {type: 'MixedTypeAnnotation'}; + case 'ObjectTypeAnnotation': + return { + type: 'ObjectTypeAnnotation', + properties: parser + .getObjectProperties(typeAnnotation) + .map(member => + buildPropertiesForEvent(member, parser, getPropertyType), + ), + }; + case 'ArrayTypeAnnotation': + return { + type: 'ArrayTypeAnnotation', + elementType: extractArrayElementType( + typeAnnotation.elementType, + name, + parser, + ), + }; + default: + throw new Error( + `Unrecognized ${type} for Array ${name} in events.\n${JSON.stringify( + typeAnnotation, + null, + 2, + )}`, + ); + } +} + +module.exports = { + getPropertyType, + extractArrayElementType, +}; diff --git a/packages/react-native-codegen/src/parsers/flow/components/commands.js b/packages/react-native-codegen/src/parsers/flow/components/commands.js index 8800427a6157..966e332674dc 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/commands.js +++ b/packages/react-native-codegen/src/parsers/flow/components/commands.js @@ -13,12 +13,14 @@ import type { CommandParamTypeAnnotation, CommandTypeAnnotation, - ComponentCommandArrayTypeAnnotation, NamedShape, } from '../../../CodegenSchema.js'; import type {Parser} from '../../parser'; import type {TypeDeclarationMap} from '../../utils'; +const { + getCommandArrayElementTypeType, +} = require('../../components/commands-commons'); const {getValueFromTypes} = require('../utils.js'); // $FlowFixMe[unclear-type] there's no flowtype for ASTs @@ -157,72 +159,6 @@ function buildCommandSchema( }; } -type Allowed = ComponentCommandArrayTypeAnnotation['elementType']; - -function getCommandArrayElementTypeType( - inputType: unknown, - parser: Parser, -): Allowed { - // TODO: T172453752 support more complex type annotation for array element - if (typeof inputType !== 'object') { - throw new Error('Expected an object'); - } - - const type = inputType?.type; - - if (inputType == null || typeof type !== 'string') { - throw new Error('Command array element type must be a string'); - } - - switch (type) { - case 'BooleanTypeAnnotation': - return { - type: 'BooleanTypeAnnotation', - }; - case 'StringTypeAnnotation': - return { - type: 'StringTypeAnnotation', - }; - case 'GenericTypeAnnotation': - const name = - typeof inputType.id === 'object' - ? parser.getTypeAnnotationName(inputType) - : null; - - if (typeof name !== 'string') { - throw new Error( - 'Expected GenericTypeAnnotation AST name to be a string', - ); - } - - switch (name) { - case 'Int32': - return { - type: 'Int32TypeAnnotation', - }; - case 'Float': - return { - type: 'FloatTypeAnnotation', - }; - case 'Double': - return { - type: 'DoubleTypeAnnotation', - }; - default: - // This is not a great solution. This generally means its a type alias to another type - // like an object or union. Ideally we'd encode that in the schema so the compat-check can - // validate those deeper objects for breaking changes and the generators can do something smarter. - // As of now, the generators just create ReadableMap or (const NSArray *) which are untyped - return { - type: 'MixedTypeAnnotation', - }; - } - - default: - throw new Error(`Unsupported array element type ${type}`); - } -} - function getCommands( commandTypeAST: ReadonlyArray, types: TypeDeclarationMap, diff --git a/packages/react-native-codegen/src/parsers/flow/components/events.js b/packages/react-native-codegen/src/parsers/flow/components/events.js index 1c6d05fe282c..191264f740d8 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/events.js +++ b/packages/react-native-codegen/src/parsers/flow/components/events.js @@ -10,174 +10,24 @@ 'use strict'; -import type { - EventTypeAnnotation, - EventTypeShape, - NamedShape, -} from '../../../CodegenSchema.js'; +import type {EventTypeShape} from '../../../CodegenSchema.js'; import type {Parser} from '../../parser'; import type {EventArgumentReturnType} from '../../parsers-commons'; +const { + extractArrayElementType, + getPropertyType, +} = require('../../components/events-commons'); const { throwIfArgumentPropsAreNull, throwIfBubblingTypeIsNull, throwIfEventHasNoName, } = require('../../error-utils'); const { - buildPropertiesForEvent, emitBuildEventSchema, getEventArgument, handleEventHandler, } = require('../../parsers-commons'); -const { - emitBoolProp, - emitDoubleProp, - emitFloatProp, - emitInt32Prop, - emitMixedProp, - emitObjectProp, - emitStringProp, - emitUnionProp, -} = require('../../parsers-primitives'); - -function getPropertyType( - /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ - name: string, - optional: boolean, - typeAnnotation: $FlowFixMe, - parser: Parser, -): NamedShape { - const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); - - switch (type) { - case 'BooleanTypeAnnotation': - return emitBoolProp(name, optional); - case 'StringTypeAnnotation': - return emitStringProp(name, optional); - case 'Int32': - return emitInt32Prop(name, optional); - case 'Double': - return emitDoubleProp(name, optional); - case 'Float': - return emitFloatProp(name, optional); - case '$ReadOnly': - case 'Readonly': - return getPropertyType( - name, - optional, - typeAnnotation.typeParameters.params[0], - parser, - ); - case 'ObjectTypeAnnotation': - return emitObjectProp( - name, - optional, - parser, - typeAnnotation, - extractArrayElementType, - ); - case 'UnionTypeAnnotation': - return emitUnionProp(name, optional, parser, typeAnnotation); - case 'UnsafeMixed': - return emitMixedProp(name, optional); - case 'ArrayTypeAnnotation': - case '$ReadOnlyArray': - case 'ReadonlyArray': - return { - name, - optional, - typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), - }; - default: - throw new Error(`Unable to determine event type for "${name}": ${type}`); - } -} - -function extractArrayElementType( - typeAnnotation: $FlowFixMe, - name: string, - parser: Parser, -): EventTypeAnnotation { - const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); - - switch (type) { - case 'BooleanTypeAnnotation': - return {type: 'BooleanTypeAnnotation'}; - case 'StringTypeAnnotation': - return {type: 'StringTypeAnnotation'}; - case 'Int32': - return {type: 'Int32TypeAnnotation'}; - case 'Float': - return {type: 'FloatTypeAnnotation'}; - case 'NumberTypeAnnotation': - case 'Double': - return { - type: 'DoubleTypeAnnotation', - }; - case 'UnionTypeAnnotation': - return { - type: 'UnionTypeAnnotation', - types: typeAnnotation.types.map(option => ({ - type: 'StringLiteralTypeAnnotation', - value: parser.getLiteralValue(option), - })), - }; - case 'UnsafeMixed': - return {type: 'MixedTypeAnnotation'}; - case 'ObjectTypeAnnotation': - return { - type: 'ObjectTypeAnnotation', - properties: parser - .getObjectProperties(typeAnnotation) - .map(member => - buildPropertiesForEvent(member, parser, getPropertyType), - ), - }; - case 'ArrayTypeAnnotation': - return { - type: 'ArrayTypeAnnotation', - elementType: extractArrayElementType( - typeAnnotation.elementType, - name, - parser, - ), - }; - case '$ReadOnlyArray': - case 'ReadonlyArray': - const genericParams = typeAnnotation.typeParameters.params; - if (genericParams.length !== 1) { - throw new Error( - `Events only supports arrays with 1 Generic type. Found ${ - genericParams.length - } types:\n${prettify(genericParams)}`, - ); - } - return { - type: 'ArrayTypeAnnotation', - elementType: extractArrayElementType(genericParams[0], name, parser), - }; - default: - throw new Error( - `Unrecognized ${type} for Array ${name} in events.\n${prettify( - typeAnnotation, - )}`, - ); - } -} - -function prettify(jsonObject: $FlowFixMe): string { - return JSON.stringify(jsonObject, null, 2); -} - -function extractTypeFromTypeAnnotation( - typeAnnotation: $FlowFixMe, - parser: Parser, -): string { - return typeAnnotation.type === 'GenericTypeAnnotation' - ? parser.getTypeAnnotationName(typeAnnotation) - : typeAnnotation.type; -} function findEventArgumentsAndType( parser: Parser, diff --git a/packages/react-native-codegen/src/parsers/flow/parser.js b/packages/react-native-codegen/src/parsers/flow/parser.js index bf3c77b2ffe7..ed2ce48d79b4 100644 --- a/packages/react-native-codegen/src/parsers/flow/parser.js +++ b/packages/react-native-codegen/src/parsers/flow/parser.js @@ -548,7 +548,7 @@ class FlowParser implements Parser { extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string { return typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name + ? this.getTypeAnnotationName(typeAnnotation) : typeAnnotation.type; } diff --git a/packages/react-native-codegen/src/parsers/typescript/components/commands.js b/packages/react-native-codegen/src/parsers/typescript/components/commands.js index f51d7ccede32..bec6c8007a4c 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/commands.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/commands.js @@ -13,12 +13,14 @@ import type { CommandParamTypeAnnotation, CommandTypeAnnotation, - ComponentCommandArrayTypeAnnotation, NamedShape, } from '../../../CodegenSchema.js'; import type {Parser} from '../../parser'; import type {TypeDeclarationMap} from '../../utils'; +const { + getCommandArrayElementTypeType, +} = require('../../components/commands-commons'); const {parseTopLevelType} = require('../parseTopLevelType'); const {getPrimitiveTypeAnnotation} = require('./componentsUtils'); @@ -128,47 +130,6 @@ function buildCommandSchemaInternal( }; } -function getCommandArrayElementTypeType( - inputType: unknown, - parser: Parser, -): ComponentCommandArrayTypeAnnotation['elementType'] { - // TODO: T172453752 support more complex type annotation for array element - - if (inputType == null || typeof inputType !== 'object') { - throw new Error(`Expected an object, received ${typeof inputType}`); - } - - const type = inputType.type; - if (typeof type !== 'string') { - throw new Error('Command array element type must be a string'); - } - - // This is not a great solution. This generally means its a type alias to another type - // like an object or union. Ideally we'd encode that in the schema so the compat-check can - // validate those deeper objects for breaking changes and the generators can do something smarter. - // As of now, the generators just create ReadableMap or (const NSArray *) which are untyped - if (type === 'TSTypeReference') { - const name = - typeof inputType.typeName === 'object' - ? parser.getTypeAnnotationName(inputType) - : null; - - if (typeof name !== 'string') { - throw new Error('Expected TSTypeReference AST name to be a string'); - } - - try { - return getPrimitiveTypeAnnotation(name); - } catch (e) { - return { - type: 'MixedTypeAnnotation', - }; - } - } - - return getPrimitiveTypeAnnotation(type); -} - function buildCommandSchema( property: EventTypeAST, types: TypeDeclarationMap, diff --git a/packages/react-native-codegen/src/parsers/typescript/components/events.js b/packages/react-native-codegen/src/parsers/typescript/components/events.js index faa4bc11c0ae..a57864b6e90f 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/events.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/events.js @@ -18,157 +18,42 @@ import type { import type {Parser} from '../../parser'; import type {TypeDeclarationMap} from '../../utils'; +const { + extractArrayElementType, + getPropertyType: getPropertyTypeCommon, +} = require('../../components/events-commons'); const { throwIfArgumentPropsAreNull, throwIfBubblingTypeIsNull, throwIfEventHasNoName, } = require('../../error-utils'); const { - buildPropertiesForEvent, emitBuildEventSchema, getEventArgument, handleEventHandler, } = require('../../parsers-commons'); -const { - emitBoolProp, - emitDoubleProp, - emitFloatProp, - emitInt32Prop, - emitMixedProp, - emitObjectProp, - emitStringProp, - emitUnionProp, -} = require('../../parsers-primitives'); const {parseTopLevelType} = require('../parseTopLevelType'); const {flattenProperties} = require('./componentsUtils'); +/** + * TypeScript wrapper around the shared getPropertyType that applies + * parseTopLevelType to unwrap Readonly, WithDefault, and nullable unions + * before delegating to the shared type resolution logic. + */ function getPropertyType( /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's * LTI update could not be added via codemod */ - name, + name: string, optionalProperty: boolean, /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's * LTI update could not be added via codemod */ - annotation, + annotation: $FlowFixMe, parser: Parser, ): NamedShape { const topLevelType = parseTopLevelType(annotation, parser); const typeAnnotation = topLevelType.type; const optional = optionalProperty || topLevelType.optional; - const type = - typeAnnotation.type === 'TSTypeReference' - ? parser.getTypeAnnotationName(typeAnnotation) - : typeAnnotation.type; - - switch (type) { - case 'TSBooleanKeyword': - return emitBoolProp(name, optional); - case 'TSStringKeyword': - return emitStringProp(name, optional); - case 'Int32': - return emitInt32Prop(name, optional); - case 'Double': - return emitDoubleProp(name, optional); - case 'Float': - return emitFloatProp(name, optional); - case 'TSTypeLiteral': - return emitObjectProp( - name, - optional, - parser, - typeAnnotation, - extractArrayElementType, - ); - case 'TSUnionType': - return emitUnionProp(name, optional, parser, typeAnnotation); - case 'UnsafeMixed': - return emitMixedProp(name, optional); - case 'TSArrayType': - return { - name, - optional, - typeAnnotation: extractArrayElementType(typeAnnotation, name, parser), - }; - default: - throw new Error(`Unable to determine event type for "${name}": ${type}`); - } -} - -function extractArrayElementType( - typeAnnotation: $FlowFixMe, - name: string, - parser: Parser, -): EventTypeAnnotation { - const type = extractTypeFromTypeAnnotation(typeAnnotation, parser); - - switch (type) { - case 'TSParenthesizedType': - return extractArrayElementType( - typeAnnotation.typeAnnotation, - name, - parser, - ); - case 'TSBooleanKeyword': - return {type: 'BooleanTypeAnnotation'}; - case 'TSStringKeyword': - return {type: 'StringTypeAnnotation'}; - case 'Float': - return { - type: 'FloatTypeAnnotation', - }; - case 'Int32': - return { - type: 'Int32TypeAnnotation', - }; - case 'TSNumberKeyword': - case 'Double': - return { - type: 'DoubleTypeAnnotation', - }; - case 'TSUnionType': - return { - type: 'UnionTypeAnnotation', - types: typeAnnotation.types.map(option => ({ - type: 'StringLiteralTypeAnnotation', - value: parser.getLiteralValue(option), - })), - }; - case 'TSTypeLiteral': - return { - type: 'ObjectTypeAnnotation', - properties: parser - .getObjectProperties(typeAnnotation) - .map(member => - buildPropertiesForEvent(member, parser, getPropertyType), - ), - }; - case 'TSArrayType': - return { - type: 'ArrayTypeAnnotation', - elementType: extractArrayElementType( - typeAnnotation.elementType, - name, - parser, - ), - }; - default: - throw new Error( - `Unrecognized ${type} for Array ${name} in events.\n${JSON.stringify( - typeAnnotation, - null, - 2, - )}`, - ); - } -} - -function extractTypeFromTypeAnnotation( - typeAnnotation: $FlowFixMe, - parser: Parser, -): string { - return typeAnnotation.type === 'TSTypeReference' - ? parser.getTypeAnnotationName(typeAnnotation) - : typeAnnotation.type; + return getPropertyTypeCommon(name, optional, typeAnnotation, parser); } function findEventArgumentsAndType( diff --git a/packages/react-native-codegen/src/parsers/typescript/parser.js b/packages/react-native-codegen/src/parsers/typescript/parser.js index 86c9bdfade58..4478d0f4b31b 100644 --- a/packages/react-native-codegen/src/parsers/typescript/parser.js +++ b/packages/react-native-codegen/src/parsers/typescript/parser.js @@ -401,6 +401,8 @@ class TypeScriptParser implements Parser { return 'StringTypeAnnotation'; case 'TSTypeLiteral': return 'ObjectTypeAnnotation'; + case 'TSUnionType': + return 'UnionTypeAnnotation'; case 'TSUnknownKeyword': return 'MixedTypeAnnotation'; } @@ -603,7 +605,7 @@ class TypeScriptParser implements Parser { extractTypeFromTypeAnnotation(typeAnnotation: $FlowFixMe): string { return typeAnnotation.type === 'TSTypeReference' - ? typeAnnotation.typeName.name + ? this.getTypeAnnotationName(typeAnnotation) : typeAnnotation.type; }