facebook/flow · error · Error
Unexpected function parameter
Error message
Unexpected function parameter ${param.type} What it means
Thrown by flow-api-translator while converting TypeScript definitions to Flow definitions (TSDefToFlowDef.js). _partitionAndTranslateTSFunctionParams only maps function parameters that are Identifier, ArrayPattern, or ObjectPattern nodes (plus a leading `this` Identifier and a trailing RestElement). Any other ESTree parameter node type hits the bare `throw new Error`, which bypasses the recoverFromErrors machinery used elsewhere in the file.
Solutions
- Rewrite the offending declaration to use an optional parameter instead of a default value, e.g. `declare function f(a?: number): void` instead of `declare function f(a = 1): void`.
- Locate the param by searching your d.ts for `=` inside parameter lists of declare function/interface/constructor signatures and remove those defaults.
- Wrap the translate call in try/catch per-file and skip/report files that use unsupported parameter forms.
- File an issue on flowlint/flow repo with the repro d.ts so the param type gets an explicit unsupportedFeature recovery path instead of a raw throw.
Example fix
// before (input .d.ts) declare function connect(endpoint: string, retries = 3): void; // after ndeclare function connect(endpoint: string, retries?: number): void;
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-scan d.ts source for default-initialized params before translating
function hasUnsupportedFnParams(tsSource) {
// AssignmentPattern = '=' default value inside a declare signature's param list
return /(?:function\s+\w+|interface\s+\w+[\s\S]*?)[<(][^()=]*=\s*[^,)>]/.test(tsSource);
} Type guard
const SUPPORTED_PARAMS = new Set(['Identifier', 'ArrayPattern', 'ObjectPattern', 'RestElement']);
function paramsAreSupported(fnLikeNode) {
return fnLikeNode.params.every((p) => SUPPORTED_PARAMS.has(p.type));
} Try / catch
try {
const result = await unstable_translateTSDefToFlowDef({code: dts, recoverFromErrors: true});
} catch (e) {
if (/^Unexpected function parameter/.test(e.message)) {
reportFile(file, 'unsupported param form (default value / parameter property) — rewrite as optional param');
continue; // skip file, keep batch running
}
throw e;
} Prevention
- Keep .d.ts inputs free of default values in declaration parameters; use optional markers instead.
- Run translation in per-file try/catch in batch tools so one bad declaration does not abort the run.
- Pass recoverFromErrors: true so recoverable constructs degrade to comments rather than throws.
When it happens
Trigger: Calling unstable_translateTSDefToFlowDef on .d.ts code containing function/method signature parameters the translator does not model, e.g. `declare function f(a = 1): void` (AssignmentPattern), constructor parameter properties, or decorators on parameters. Only three param shapes are handled: Identifier, ArrayPattern, ObjectPattern.
Common situations: Converting real-world .d.ts files that use default-initialized parameters in declarations; TS interface method signatures with unusual param nodes; running codemods over large declaration bundles where one unhandled param aborts the whole translation.
Related errors
- flowImportTo: Unexpected transform result.
- unable to resolve scope
- Cannot insert array into non-array parent type
- CommonJS exports cannot be combined with ES module exports.
- createTranslationContext: Module scope not found
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/0f695d497dcff05c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/flow-api-translator/src/TSDefToFlowDef.js:1023
} else if (
param.type === 'ArrayPattern' ||
param.type === 'ObjectPattern'
) {
return constructFlowNode<FlowESTree.FunctionTypeParam>({
type: 'FunctionTypeParam',
name: constructFlowNode<FlowESTree.Identifier>({
type: 'Identifier',
name: `$$param${i}$`,
optional: false,
typeAnnotation: null,
}),
optional: Boolean(param.optional),
typeAnnotation: Transform.TSTypeAnnotationOpt(
param.typeAnnotation?.typeAnnotation,
),
});
} else {
throw new Error(`Unexpected function parameter ${param.type}`);
}
}),
};
}
static TSImportType(
node: TSESTree.TSImportType,
): FlowESTree.TypeAnnotationType {
const source =
node.argument ??
(node.source == null
? null
: ({
type: 'TSLiteralType',
loc: node.source.loc,
literal: node.source,
} as TSESTree.TSLiteralType));
if (source == null) {View on GitHub (pinned to f88ac94bcf)