{"record":{"id":"0f695d497dcff05c","repo":"facebook/flow","slug":"unexpected-function-parameter-param-type","errorCode":null,"errorMessage":"Unexpected function parameter ${param.type}","messagePattern":"Unexpected function parameter (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/flow-api-translator/src/TSDefToFlowDef.js","lineNumber":1023,"sourceCode":"          } else if (\n            param.type === 'ArrayPattern' ||\n            param.type === 'ObjectPattern'\n          ) {\n            return constructFlowNode<FlowESTree.FunctionTypeParam>({\n              type: 'FunctionTypeParam',\n              name: constructFlowNode<FlowESTree.Identifier>({\n                type: 'Identifier',\n                name: `$$param${i}$`,\n                optional: false,\n                typeAnnotation: null,\n              }),\n              optional: Boolean(param.optional),\n              typeAnnotation: Transform.TSTypeAnnotationOpt(\n                param.typeAnnotation?.typeAnnotation,\n              ),\n            });\n          } else {\n            throw new Error(`Unexpected function parameter ${param.type}`);\n          }\n        }),\n      };\n    }\n\n    static TSImportType(\n      node: TSESTree.TSImportType,\n    ): FlowESTree.TypeAnnotationType {\n      const source =\n        node.argument ??\n        (node.source == null\n          ? null\n          : ({\n              type: 'TSLiteralType',\n              loc: node.source.loc,\n              literal: node.source,\n            } as TSESTree.TSLiteralType));\n      if (source == null) {","sourceCodeStart":1005,"sourceCodeEnd":1041,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-api-translator/src/TSDefToFlowDef.js#L1005-L1041","documentation":"Thrown by flow-api-translator while converting a TypeScript declaration AST into a Flow definition. When mapping a function signature's parameter list it handles only Identifier, ArrayPattern, and ObjectPattern parameters (plus a leading `this` Identifier and a trailing RestElement); any other parameter node type reaches the else branch and throws, naming the node type.","triggerScenarios":"Calling the TSDefToFlowDef transform (e.g. translating a .d.ts file to Flow defs) on a TS AST containing a function-type parameter that is not Identifier/ArrayPattern/ObjectPattern — for example a TSParameterProperty from `constructor(private x: string)` style signatures, an AssignmentPattern, or an unexpected node shape produced by a different parser or TypeScript version.","commonSituations":"Translating .d.ts files that use constructor parameter properties; declarations generated by TypeScript versions whose AST shapes the translator does not know; hand-built or post-processed ASTs passed directly to the transform; translator and TypeScript versions out of sync.","solutions":["Update flow-api-translator to the latest version — newer versions handle more parameter node types","Grep the input .d.ts for constructor parameter properties (`constructor(private|protected|public ...)`) and rewrite them as an explicit property plus a plain parameter, since the message names the offending node type","If you build the TS AST yourself, normalize parameters to Identifier/ArrayPattern/ObjectPattern before calling the transform","If the input is valid TypeScript, file an issue with the minimal .d.ts that reproduces it"],"exampleFix":"// before (input .d.ts)\ndeclare class Foo {\n  constructor(private name: string): void;\n}\n\n// after (input .d.ts)\ndeclare class Foo {\n  name: string;\n  constructor(name: string): void;\n}","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_PARAMS = new Set(['Identifier', 'ArrayPattern', 'ObjectPattern']);\n\nfunction functionParamsSupported(fn: {\n  params: ReadonlyArray<{ type: string }>;\n}): boolean {\n  return fn.params.every(\n    (p) =>\n      SUPPORTED_PARAMS.has(p.type) ||\n      // leading `this` and trailing rest params are handled specially\n      (p.type === 'Identifier') ,\n  );\n}\n// walk the TS AST and run functionParamsSupported on every function-ish\n// node before handing the file to TSDefToFlowDef","typeGuard":"function isSupportedParamType(\n  type: string,\n): type is 'Identifier' | 'ArrayPattern' | 'ObjectPattern' {\n  return type === 'Identifier' || type === 'ArrayPattern' || type === 'ObjectPattern';\n}","tryCatchPattern":"try {\n  const flowDef = translateTSDefToFlowDef(tsAst);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unexpected function parameter')) {\n    // report the .d.ts path + the param type from the message, skip the file\n    report.skipped(file, err.message);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Avoid constructor parameter properties in published .d.ts files","Pre-filter declaration files in CI by translating all of them in a smoke step","Keep flow-api-translator updated alongside your TypeScript version","When generating ASTs programmatically, emit plain Identifier parameters"],"tags":["typescript","flow","dts","ast","transformation"],"backgroundTag":"unsupported-ast-node-type","analyzedSha":"d1341dac899a79c027762f6b423d896045287620","analyzedAt":"2026-08-17T00:07:02.212Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}