- Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
The rewrittenFileExtensions comment says the order follows TypeScript:
https://github.com/evanw/esbuild/blob/main/internal/resolver/resolver.go#L1723-L1730
// Note that the official compiler code always tries ".ts" before // ".tsx" even if the original extension was ".jsx". ".jsx": {".ts", ".tsx"},This was added in 0cdc005 (Aug 2020, "fix for #118: replace js/jsx with ts/tsx like tsc") and was accurate for TypeScript at that time.
In TypeScript ≤4.x, tryAddingExtensions had no special case for .Jsx — it fell through to default which always tried .ts then .tsx:
// TypeScript ≤4.x — src/compiler/moduleNameResolver.ts // .Jsx had no explicit case, so it fell through to default: case Extension.Ts: case Extension.Tsx: case Extension.Dts: // falls through default: return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx)In TypeScript 5.0 (PR #51435, merged 89e928e8b4, Jan 2023), tryAddingExtensions was restructured for --allowArbitraryExtensions. As part of that refactor, .Jsx got its own explicit case with reversed order:
https://github.com/microsoft/TypeScript/blob/main/src/compiler/moduleNameResolver.ts#L2159-L2167
// TypeScript 5.0+ — src/compiler/moduleNameResolver.ts case Extension.Tsx: case Extension.Jsx: // basically identical to the ts/js case below, but prefers matching // tsx and jsx files exactly before falling back to the ts or js file path return tryExtension(Extension.Tsx, ...) || tryExtension(Extension.Ts, ...)TypeScript's comment indicates this was intentional — .jsx implies JSX, so .tsx is the closer match.
The rewrittenFileExtensions map hasn't been modified since the original 2020 commit. This only matters when both file.ts and file.tsx exist for the same .jsx import — an unlikely scenario. Just flagging it since the comment references TypeScript's behavior.