diff --git a/src/parser/plugins/types.ts b/src/parser/plugins/types.ts index 27e20ecf..935c289a 100644 --- a/src/parser/plugins/types.ts +++ b/src/parser/plugins/types.ts @@ -12,9 +12,13 @@ import {tsParseTypeAnnotation} from "./typescript"; // An apparent conditional expression could actually be an optional parameter in an arrow function. export function typedParseConditional(noIn: boolean): void { // If we see ?:, this can't possibly be a valid conditional. typedParseParenItem will be called - // later to finish off the arrow parameter. - if (match(tt.question) && lookaheadType() === tt.colon) { - return; + // later to finish off the arrow parameter. We also need to handle bare ? tokens for optional + // parameters without type annotations, i.e. ?, and ?) . + if (match(tt.question)) { + const nextType = lookaheadType(); + if (nextType === tt.colon || nextType === tt.comma || nextType === tt.parenR) { + return; + } } baseParseConditional(noIn); } diff --git a/test/types-test.ts b/test/types-test.ts index 5991839f..7d2e1e2f 100644 --- a/test/types-test.ts +++ b/test/types-test.ts @@ -470,4 +470,21 @@ describe("type transforms", () => { `, ); }); + + it("handles optional params without type annotations", () => { + assertTypeScriptAndFlowResult( + ` + const test = (a?) => a; + function test2(a?) { + return a; + } + `, + `"use strict"; + const test = (a) => a; + function test2(a) { + return a; + } + `, + ); + }); });