Comparisons
Pairs that get conflated in real conversations, and in real pull requests. Neither column wins — what decides is the requirement. Each record leads with the confusion, because the confusion is the reason the record exists.
Polyfills vs Transpilation
Both are filed under "browser support" and configured in the same build step, so people assume one setting covers both. It does not, and the failure modes are different in a way that matters. A syntax the parser does not understand is a parse error: the whole script fails before a single line runs, and it fails at load, which is loud. A missing runtime API is a TypeError at the moment that line executes, which may be deep inside a rarely-used branch and may only happen for the small slice of users on that engine — quiet, late, and hard to reproduce. The other half of the confusion is the cost: transpiled output is usually a little larger and occasionally slower, while a polyfill is real code shipped to every user including the ones who did not need it, which is why conditional or feature-detected loading exists. And a polyfill cannot always be faithful — some behaviour is not implementable from userland at all.
When the target browser's parser does not understand the syntax you wrote — optional chaining, class fields, async generators, JSX, TypeScript type annotations. The compiler rewrites it into syntax the parser accepts.
When the syntax parses fine but the object, method or global does not exist at runtime — a newer Array or String method, a constructor, an observer API. Code is added that defines it.
| Dimension | Transpilation (down-levelling syntax) | Polyfilling (supplying a missing runtime API) |
|---|---|---|
| Fixes | Syntax the parser rejects | Objects and methods that do not exist |
| Failure without it | Parse error — the whole file never runs | TypeError at the call site, possibly much later |
| Applied by | A compiler rewriting your source | Extra code that runs before yours |
| Ships to users | Rewritten equivalent of your own code | Additional library code, often for everyone |
| Detectable at runtime | No — it already happened at build time | Yes — feature detection is how conditional loading works |
| Can it always be done | Usually, though output may be larger or slower | No — some platform behaviour cannot be reproduced in userland |
| Typical config | Compiler target and browser list | A polyfill library, ideally loaded conditionally |