Closed
Description
Restricting --moduleResolution bundler
to --module esnext
--moduleResolution bundler
- Some confusion due to a footgun.
- When we look at
package.json
'sexports
field, we always look at theimport
condition, never therequire
.
- When we look at
- For example, import
import "yargs"
--moduleResolution nodenext
depends on thepackage.json
type
field for a.ts
or.js
file--moduleResolution bundler
just looks at the syntax, regardless of the file type.require
uses therequire
condition,imports
use theimport
condition.
- If you're using this mode, what is your end goal? What is the "correct" output target?
- Bundlers usually prefer ES modules format.
- But if you use
--module commonjs
, the output forimport "foo"
will berequire("foo")
- and bundlers will switch their resolution strategy compared to what TypeScript actually does.- This is a footgun!
- Proposal: limit this mode to
--module esnext
.- What about a stable ES module target apart from ESNext?
- es2015 - basic module syntax
- es2020 -
import.meta
- es2022 - top-level
await
- What about a stable ES module target apart from ESNext?
- Aside: respecting
__esModule
markers not consistent across bundlers.- It might make sense to have a corresponding
--module
target for--moduleResolution bundler
- But it would be bad to call it that - we have no interest in bundling.
- It might make sense to have a corresponding
- Conclusion: limit
--module
toesnext
for--moduleResolution bundler
Consulting valueOf()
in Relational Comparisons
-
Idea: consult
.valueOf()
to see if JS relational comparisons are valid. -
Found bugs
- VS Code issue with sorting URIs by last-touched time - accidentally comparing the functions that would actually update the time instead of the times themselves.
- Comparison on opaque types - fine at runtime, plausible bug long term. If these were branded intead of opaque, it would work better.
-
How do you deal with this?
function compare<T extends string | number>(x: T, y: T) { return x < y; }
- Cast both sides to
string
or tonumber
? Not correct. - Cast both to
any
? Ehh
- Cast both sides to
-
Weird to say we'd just support
valueOf
but not[Symbol.toPrimitive]
- Do people actually define these?
- Separately of each other?
- Moment doesn't
- Sure but other code does, and might?
- Admittedly, the interplay between these is not 100% clear. Which one is used by the other?
-
Still, feels like it's an overall reasonable change.
-
We would like to investigate bringing it in for TypeScript 5.1.