Fix interface support in turbo module TypeScript codegen (component only) (#34778)
Summary: Interface was supported in component, but it only allows interfaces in limited cases. In this change, I extended interface support to all places where object literal type is supported. I also refactor the code so that properties and events are able to share the same implementation. In order not to mess up the diff, I noticed that implementations are repeated in processing array properties and non-array properties. But I leave it without refactoring. I will do it in future PRs. I also commented potential problems I found in the code. ## Changelog [General] [Changed] - Fix interface support in turbo module TypeScript codegen (component only) Pull Request resolved: https://github.com/facebook/react-native/pull/34778 Test Plan: `yarn jest react-native-codegen` passed Reviewed By: cortinico Differential Revision: D39809230 Pulled By: cipolleschi fbshipit-source-id: cfb51ce915249b5abceafee1c08b7e5762d03519
This commit is contained in:
Родитель
e78a495900
Коммит
8dc6bec719
|
@ -17,7 +17,11 @@ const flowSnaps = require('../../../../src/parsers/flow/components/__tests__/__s
|
|||
const flowExtraCases = [];
|
||||
const tsFixtures = require('../../typescript/components/__test_fixtures__/fixtures.js');
|
||||
const tsSnaps = require('../../../../src/parsers/typescript/components/__tests__/__snapshots__/typescript-component-parser-test.js.snap');
|
||||
const tsExtraCases = ['ARRAY2_PROP_TYPES_NO_EVENTS', 'ARRAY2_STATE_TYPES'];
|
||||
const tsExtraCases = [
|
||||
'ARRAY2_PROP_TYPES_NO_EVENTS',
|
||||
'ARRAY2_STATE_TYPES',
|
||||
'PROPS_AND_EVENTS_WITH_INTERFACES',
|
||||
];
|
||||
const ignoredCases = ['ARRAY_PROP_TYPES_NO_EVENTS', 'ARRAY_STATE_TYPES'];
|
||||
|
||||
compareSnaps(
|
||||
|
|
|
@ -1095,6 +1095,49 @@ export default codegenNativeComponent<ModuleProps>(
|
|||
) as NativeType;
|
||||
`;
|
||||
|
||||
const PROPS_AND_EVENTS_WITH_INTERFACES = `
|
||||
import type {
|
||||
BubblingEventHandler,
|
||||
DirectEventHandler,
|
||||
Int32,
|
||||
} from 'CodegenTypes';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {HostComponent} from 'react-native';
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
export interface Base1 {
|
||||
readonly x: string;
|
||||
}
|
||||
|
||||
export interface Base2 {
|
||||
readonly y: Int32;
|
||||
}
|
||||
|
||||
export interface Derived extends Base1, Base2 {
|
||||
readonly z: boolean;
|
||||
}
|
||||
|
||||
export interface ModuleProps extends ViewProps {
|
||||
// Props
|
||||
ordinary_prop: Derived;
|
||||
readonly_prop: Readonly<Derived>;
|
||||
ordinary_array_prop?: readonly Derived[];
|
||||
readonly_array_prop?: readonly Readonly<Derived>[];
|
||||
ordinary_nested_array_prop?: readonly Derived[][];
|
||||
readonly_nested_array_prop?: readonly Readonly<Derived>[][];
|
||||
|
||||
// Events
|
||||
onDirect: DirectEventHandler<Derived>;
|
||||
onBubbling: BubblingEventHandler<Readonly<Derived>>;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<ModuleProps>('Module', {
|
||||
interfaceOnly: true,
|
||||
paperComponentName: 'RCTModule',
|
||||
}) as HostComponent<ModuleProps>;
|
||||
`;
|
||||
|
||||
// === STATE ===
|
||||
const ALL_STATE_TYPES = `
|
||||
/**
|
||||
|
@ -1630,6 +1673,7 @@ module.exports = {
|
|||
COMMANDS_DEFINED_WITH_ALL_TYPES,
|
||||
PROPS_AS_EXTERNAL_TYPES,
|
||||
COMMANDS_WITH_EXTERNAL_TYPES,
|
||||
PROPS_AND_EVENTS_WITH_INTERFACES,
|
||||
ALL_STATE_TYPES,
|
||||
ARRAY_STATE_TYPES,
|
||||
ARRAY2_STATE_TYPES,
|
||||
|
|
|
@ -12640,6 +12640,317 @@ exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_TYPE
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AND_EVENTS_WITH_INTERFACES 1`] = `
|
||||
"{
|
||||
'modules': {
|
||||
'Module': {
|
||||
'type': 'Component',
|
||||
'components': {
|
||||
'Module': {
|
||||
'interfaceOnly': true,
|
||||
'paperComponentName': 'RCTModule',
|
||||
'extendsProps': [
|
||||
{
|
||||
'type': 'ReactNativeBuiltInType',
|
||||
'knownTypeName': 'ReactNativeCoreViewProps'
|
||||
}
|
||||
],
|
||||
'events': [
|
||||
{
|
||||
'name': 'onDirect',
|
||||
'optional': false,
|
||||
'bubblingType': 'direct',
|
||||
'typeAnnotation': {
|
||||
'type': 'EventTypeAnnotation',
|
||||
'argument': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'onBubbling',
|
||||
'optional': false,
|
||||
'bubblingType': 'bubble',
|
||||
'typeAnnotation': {
|
||||
'type': 'EventTypeAnnotation',
|
||||
'argument': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation'
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
'props': [
|
||||
{
|
||||
'name': 'ordinary_prop',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'readonly_prop',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'ordinary_array_prop',
|
||||
'optional': true,
|
||||
'typeAnnotation': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'readonly_array_prop',
|
||||
'optional': true,
|
||||
'typeAnnotation': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'ordinary_nested_array_prop',
|
||||
'optional': true,
|
||||
'typeAnnotation': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'readonly_nested_array_prop',
|
||||
'optional': true,
|
||||
'typeAnnotation': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ArrayTypeAnnotation',
|
||||
'elementType': {
|
||||
'type': 'ObjectTypeAnnotation',
|
||||
'properties': [
|
||||
{
|
||||
'name': 'x',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'StringTypeAnnotation',
|
||||
'default': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'y',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'Int32TypeAnnotation',
|
||||
'default': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'z',
|
||||
'optional': false,
|
||||
'typeAnnotation': {
|
||||
'type': 'BooleanTypeAnnotation',
|
||||
'default': false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
'commands': []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`RN Codegen TypeScript Parser can generate fixture PROPS_AS_EXTERNAL_TYPES 1`] = `
|
||||
"{
|
||||
'modules': {
|
||||
|
|
|
@ -45,38 +45,29 @@ function getProperties(
|
|||
}
|
||||
|
||||
function getTypeAnnotationForObjectAsArrayElement<T>(
|
||||
objectType: $FlowFixMe,
|
||||
types: TypeDeclarationMap,
|
||||
buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
|
||||
): $FlowFixMe {
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: flattenProperties(
|
||||
objectType.typeParameters.params[0].members ||
|
||||
objectType.typeParameters.params,
|
||||
types,
|
||||
)
|
||||
.map(prop => buildSchema(prop, types))
|
||||
.filter(Boolean),
|
||||
};
|
||||
}
|
||||
|
||||
function getTypeAnnotationForArrayOfArrayOfObject<T>(
|
||||
name: string,
|
||||
typeAnnotation: $FlowFixMe,
|
||||
types: TypeDeclarationMap,
|
||||
buildSchema: (property: PropAST, types: TypeDeclarationMap) => ?NamedShape<T>,
|
||||
): $FlowFixMe {
|
||||
// We need to go yet another level deeper to resolve
|
||||
// types that may be defined in a type alias
|
||||
const nestedObjectType = getValueFromTypes(typeAnnotation, types);
|
||||
// for array of array of a type
|
||||
// such type must be an object literal
|
||||
const elementType = getTypeAnnotationForArray(
|
||||
name,
|
||||
typeAnnotation,
|
||||
null,
|
||||
types,
|
||||
buildSchema,
|
||||
);
|
||||
if (elementType.type !== 'ObjectTypeAnnotation') {
|
||||
throw new Error(
|
||||
`Only array of array of object is supported for "${name}".`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'ArrayTypeAnnotation',
|
||||
elementType: getTypeAnnotationForObjectAsArrayElement(
|
||||
nestedObjectType,
|
||||
types,
|
||||
buildSchema,
|
||||
),
|
||||
elementType,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -121,7 +112,8 @@ function getTypeAnnotationForArray<T>(
|
|||
|
||||
// Covers: T[]
|
||||
if (typeAnnotation.type === 'TSArrayType') {
|
||||
return getTypeAnnotationForArrayOfArrayOfObject(
|
||||
return getTypeAnnotationForObjectAsArrayElement(
|
||||
name,
|
||||
typeAnnotation.elementType,
|
||||
types,
|
||||
buildSchema,
|
||||
|
@ -133,8 +125,10 @@ function getTypeAnnotationForArray<T>(
|
|||
const objectType = getValueFromTypes(extractedTypeAnnotation, types);
|
||||
|
||||
if (objectType.typeName.name === 'Readonly') {
|
||||
return getTypeAnnotationForObjectAsArrayElement(
|
||||
objectType,
|
||||
return getTypeAnnotationForArray(
|
||||
name,
|
||||
objectType.typeParameters.params[0],
|
||||
defaultValue,
|
||||
types,
|
||||
buildSchema,
|
||||
);
|
||||
|
@ -142,7 +136,8 @@ function getTypeAnnotationForArray<T>(
|
|||
|
||||
// Covers: ReadonlyArray<T>
|
||||
if (objectType.typeName.name === 'ReadonlyArray') {
|
||||
return getTypeAnnotationForArrayOfArrayOfObject(
|
||||
return getTypeAnnotationForObjectAsArrayElement(
|
||||
name,
|
||||
objectType.typeParameters.params[0],
|
||||
types,
|
||||
buildSchema,
|
||||
|
@ -158,6 +153,19 @@ function getTypeAnnotationForArray<T>(
|
|||
extractedTypeAnnotation.type;
|
||||
|
||||
switch (type) {
|
||||
case 'TSTypeLiteral':
|
||||
case 'TSInterfaceDeclaration': {
|
||||
const rawProperties =
|
||||
type === 'TSInterfaceDeclaration'
|
||||
? [typeAnnotation]
|
||||
: typeAnnotation.members;
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties: flattenProperties(rawProperties, types)
|
||||
.map(prop => buildSchema(prop, types))
|
||||
.filter(Boolean),
|
||||
};
|
||||
}
|
||||
case 'TSNumberKeyword':
|
||||
return {
|
||||
type: 'FloatTypeAnnotation',
|
||||
|
@ -336,27 +344,28 @@ function getTypeAnnotation<T>(
|
|||
};
|
||||
}
|
||||
|
||||
// Covers: Readonly<T>, Readonly<{ ... }>, Readonly<T | U ...>
|
||||
if (
|
||||
(typeAnnotation.type === 'TSTypeReference' ||
|
||||
typeAnnotation.type === 'TSTypeLiteral') &&
|
||||
typeAnnotation.typeName?.name === 'Readonly'
|
||||
typeAnnotation.type === 'TSTypeReference' &&
|
||||
typeAnnotation.typeName?.name === 'Readonly' &&
|
||||
typeAnnotation.typeParameters.type === 'TSTypeParameterInstantiation'
|
||||
) {
|
||||
const rawProperties =
|
||||
typeAnnotation.typeParameters.params[0].members ||
|
||||
(typeAnnotation.typeParameters.params[0].types &&
|
||||
typeAnnotation.typeParameters.params[0].types[0].members) ||
|
||||
typeAnnotation.typeParameters.params;
|
||||
|
||||
const flattenedProperties = flattenProperties(rawProperties, types);
|
||||
|
||||
const properties = flattenedProperties
|
||||
.map(prop => buildSchema(prop, types))
|
||||
.filter(Boolean);
|
||||
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties,
|
||||
};
|
||||
// TODO:
|
||||
// the original implementation assume Readonly<TSUnionType>
|
||||
// to be Readonly<{ ... } | null | undefined>
|
||||
// without actually verifying it
|
||||
let elementType = typeAnnotation.typeParameters.params[0];
|
||||
if (elementType.type === 'TSUnionType') {
|
||||
elementType = elementType.types[0];
|
||||
}
|
||||
return getTypeAnnotation(
|
||||
name,
|
||||
elementType,
|
||||
defaultValue,
|
||||
withNullDefault,
|
||||
types,
|
||||
buildSchema,
|
||||
);
|
||||
}
|
||||
|
||||
const type =
|
||||
|
@ -366,6 +375,22 @@ function getTypeAnnotation<T>(
|
|||
: typeAnnotation.type;
|
||||
|
||||
switch (type) {
|
||||
case 'TSTypeLiteral':
|
||||
case 'TSInterfaceDeclaration': {
|
||||
const rawProperties =
|
||||
type === 'TSInterfaceDeclaration'
|
||||
? [typeAnnotation]
|
||||
: typeAnnotation.members;
|
||||
const flattenedProperties = flattenProperties(rawProperties, types);
|
||||
const properties = flattenedProperties
|
||||
.map(prop => buildSchema(prop, types))
|
||||
.filter(Boolean);
|
||||
|
||||
return {
|
||||
type: 'ObjectTypeAnnotation',
|
||||
properties,
|
||||
};
|
||||
}
|
||||
case 'ImageSource':
|
||||
return {
|
||||
type: 'ReservedPropTypeAnnotation',
|
||||
|
@ -662,11 +687,22 @@ function flattenProperties(
|
|||
getProperties(property.typeName.name, types),
|
||||
types,
|
||||
);
|
||||
} else if (property.type === 'TSExpressionWithTypeArguments') {
|
||||
} else if (
|
||||
property.type === 'TSExpressionWithTypeArguments' ||
|
||||
property.type === 'TSInterfaceHeritage'
|
||||
) {
|
||||
return flattenProperties(
|
||||
getProperties(property.expression.name, types),
|
||||
types,
|
||||
);
|
||||
} else if (property.type === 'TSTypeLiteral') {
|
||||
return flattenProperties(property.members, types);
|
||||
} else if (property.type === 'TSInterfaceDeclaration') {
|
||||
return flattenProperties(getProperties(property.id.name, types), types);
|
||||
} else {
|
||||
throw new Error(
|
||||
`${property.type} is not a supported object literal type.`,
|
||||
);
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
|
|
@ -15,6 +15,7 @@ import type {
|
|||
NamedShape,
|
||||
EventTypeAnnotation,
|
||||
} from '../../../CodegenSchema.js';
|
||||
const {flattenProperties} = require('./componentsUtils');
|
||||
|
||||
function getPropertyType(
|
||||
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
|
||||
|
@ -126,16 +127,33 @@ function findEventArgumentsAndType(
|
|||
bubblingType: void | 'direct' | 'bubble',
|
||||
paperName: ?$FlowFixMe,
|
||||
) {
|
||||
if (typeAnnotation.type === 'TSInterfaceDeclaration') {
|
||||
return {
|
||||
argumentProps: flattenProperties([typeAnnotation], types),
|
||||
paperTopLevelNameDeprecated: paperName,
|
||||
bubblingType,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeAnnotation.type === 'TSTypeLiteral') {
|
||||
return {
|
||||
argumentProps: typeAnnotation.members,
|
||||
paperTopLevelNameDeprecated: paperName,
|
||||
bubblingType,
|
||||
};
|
||||
}
|
||||
|
||||
if (!typeAnnotation.typeName) {
|
||||
throw new Error("typeAnnotation of event doesn't have a name");
|
||||
}
|
||||
const name = typeAnnotation.typeName.name;
|
||||
if (name === 'Readonly') {
|
||||
return {
|
||||
argumentProps: typeAnnotation.typeParameters.params[0].members,
|
||||
paperTopLevelNameDeprecated: paperName,
|
||||
return findEventArgumentsAndType(
|
||||
typeAnnotation.typeParameters.params[0],
|
||||
types,
|
||||
bubblingType,
|
||||
};
|
||||
paperName,
|
||||
);
|
||||
} else if (name === 'BubblingEventHandler' || name === 'DirectEventHandler') {
|
||||
const eventType = name === 'BubblingEventHandler' ? 'bubble' : 'direct';
|
||||
const paperTopLevelNameDeprecated =
|
||||
|
@ -160,8 +178,12 @@ function findEventArgumentsAndType(
|
|||
);
|
||||
}
|
||||
} else if (types[name]) {
|
||||
let elementType = types[name];
|
||||
if (elementType.type === 'TSTypeAliasDeclaration') {
|
||||
elementType = elementType.typeAnnotation;
|
||||
}
|
||||
return findEventArgumentsAndType(
|
||||
types[name].typeAnnotation,
|
||||
elementType,
|
||||
types,
|
||||
bubblingType,
|
||||
paperName,
|
||||
|
|
|
@ -125,15 +125,18 @@ function resolveTypeAnnotation(
|
|||
}
|
||||
|
||||
function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode {
|
||||
if (value.type === 'TSTypeReference' && types[value.typeName.name]) {
|
||||
return getValueFromTypes(types[value.typeName.name], types);
|
||||
switch (value.type) {
|
||||
case 'TSTypeReference':
|
||||
if (types[value.typeName.name]) {
|
||||
return getValueFromTypes(types[value.typeName.name], types);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
case 'TSTypeAliasDeclaration':
|
||||
return getValueFromTypes(value.typeAnnotation, types);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value.type === 'TSTypeAliasDeclaration') {
|
||||
return value.typeAnnotation;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
export type ParserErrorCapturer = <T>(fn: () => T) => ?T;
|
||||
|
|
Загрузка…
Ссылка в новой задаче