recast SyntaxError: Unexpected token - codemod parser chokes on newer syntax
Fixes recast SyntaxError: Unexpected token when the codemod parser chokes on newer syntax. Use it when recast's default parser cannot read modern JS or TypeScript (optional chaining, class fields, TS types). Key trigger: recast SyntaxError pointing at valid modern syntax.
recast SyntaxError: Unexpected token - codemod parser chokes on newer syntax
TL;DR: Recast's default parser predates the newer syntax in your files. Tell recast to use its bundled Babel parser instead by passing parser: require("recast/parsers/babel") (or the babel-ts variant for TypeScript). Your transform logic is fine - only the parser needs swapping.
recast SyntaxError: Unexpected token - codemod parser chokes on newer syntaxSteps
Confirm it is the parser: the SyntaxError points at a modern feature (
?.,??, class fields, TypeScript annotations) that your toolchain otherwise accepts. Expected: the flagged token is valid syntax in your project - the parser is the problem, not the code.Swap the parser where you call
recast.parse:const recast = require("recast"); const ast = recast.parse(source, { parser: require("recast/parsers/babel-ts"), });Use
recast/parsers/babelinstead ofbabel-tsfor plain JavaScript. Expected: parsing the same file now succeeds.Keep using recast's printer for output - it preserves the original formatting; only the parser changes. Expected: output diffs look the same as before, the codemod just parses further.
Re-run the full codemod. Expected: no SyntaxError; files transform as intended.
Use this when
- Recast throws
SyntaxError: Unexpected tokenon syntax that is valid in your project. - The codemod worked on older files but chokes after the codebase adopted newer syntax.
- The error comes from
recast.parse, not from your transform logic.
Not for this skill when
- The code is genuinely invalid - fix the code, not the parser.
- The
Unexpected tokencomes from jscodeshift's own parser setup - different tool, different fix. - The parse error is in the transform file itself rather than the files being transformed.
Variant phrasings
- recast unexpected token optional chaining
- recast parse typescript files
- recast babel parser codemod
Why it happens
Recast defaults to an older Esprima-based parser that predates modern syntax features. The Babel-based parsers bundled with recast understand current JavaScript and TypeScript, so pointing parse at them is the supported escape hatch.
Edge cases
babel-tscovers.tsand.tsx; plain.jswith modern syntax wants thebabelvariant.- For exotic proposals you may need to pass extra parser options through - check the parser module recast ships for the supported options shape.
- Parse with one parser and print with another and you can get reformatted output - keep both on recast to preserve formatting.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_DtvnLgYmLJkc51vn8FqOMg