Skip to content

Design Meeting Notes, 2/22/2023 #52926

Closed
Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Restricting --moduleResolution bundler to --module esnext

  • --moduleResolution bundler
  • Some confusion due to a footgun.
    • When we look at package.json's exports field, we always look at the import condition, never the require.
  • For example, import import "yargs"
    • --moduleResolution nodenext depends on the package.json type field for a .ts or .js file
    • --moduleResolution bundler just looks at the syntax, regardless of the file type. require uses the require condition, imports use the import 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 for import "foo" will be require("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
  • 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.
  • Conclusion: limit --module to esnext for --moduleResolution bundler

Consulting valueOf() in Relational Comparisons

#52807

  • 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 to number? Not correct.
    • Cast both to any? Ehh
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design NotesNotes from our design meetings

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions