TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Design Meeting Notes, 8/20/2024

Open DanielRosenwasser opened this issue 1 year ago • 2 comments

Reconsidering a flag to rewrite .ts to .js in emit in light of TS support in Node.js

https://github.com/microsoft/TypeScript/issues/59597#issuecomment-2287466184

  • Traditionally, we've said we will never rewrite any module specifier.
  • What's changed? --experimental-transform-types and --experimental-strip-types are now in Node.js.
    • Here, you must reference your files with an explicit .ts-like extension.
  • Today, we have allowImportingTsExtensions to allow this, but you must have noEmit turned on.
  • People want a mode where they can emit to .js but still reference .ts files.
    • Why?
      • Maybe you were using these transform types for development, but need to emit to JS for production.
      • Maybe you need to publish to npm (can't load .ts from node_modules).
  • So we are reconsidering TS never rewriting paths.
  • What are the rules for when TypeScript can do this?
    • Paths must begin with a . or ...
    • The path cannot be a declaration file path (i.e. one cannot explicitly reference a .d.ts file).
    • The path must be a .ts, .tsx, .cts, or .mts file.
  • .tsx
    • We will rewrite .tsx to .js if --jsx is react, react-jsx, or react-jsxdev.
    • We will rewrite .tsx to .jsx if --jsx is react-native.
  • Error checking.
    • We will do a naive transform, but we will need to see if something will improperly be transformed.
    • For example, import foo = require("./foo.ts"); will be transformed to import foo = require("./foo.js");, which is incorrect if the original file was foo.ts.ts.
    • Can we do something about incorrectimport and export subpaths?
      • We don't rewrite subpaths, but people can write exports and imports in package.json that resolve to .ts files. Won't run on publish.
      • Mmmmaybe, we haven't settled on anything on this yet.
  • Is the request something like "downleveling"?
    • Kind of. It's for older runtimes, it's for node_modules.
    • Are there other less-obvious features that need to be downleveled?
      • Don't want to over-generalize on this problem space.
  • Are there other
    • What about --outDir? Shouldn't we rewrite paths relative to outDir?
      • If you rewrite ../../other-project/src/foo.ts, don't you want to rewrite this to ../../other-project/dist/foo.js?
        • Uh.
    • moduleSuffixes?
      • Can ban this one...probably.
  • Are we fighting the tide with this stuff? Should we just say the runtime should support .ts everywhere and that's what people use?
    • Maybe long-term? There are lots of issues with that, but this is nearer-term.
  • What do we do with import type?
    • Presumably, we would rewrite these to .js as well, right?
    • We can leave them as-is technically.
    • We should test that.
  • Lots of hypotheticals around using Deno and Bun and then going broader across runtimes.
    • Is that realistic? dnt probably does this better than we can.
  • Are we going to error if users write .js imports instead of .ts? It's going to error and users are not going to know why.
  • We probably should look at if JSR does the same transforms that we're looking to do.
  • This is experimental in Node.js. Should this be experimental as well?
    • Supports other tools/use-cases as well.
  • Let's talk about dynamic import(...) calls.
    • Some of these are statically analyzable, but some are not.
      • e.g. import(someVariable);
    • One option is a runtime shim like __fixExtension.
    • Another option is to just not rewrite these at all - means you can only have static imports, and users have to write their own shimming logic before calling import() on totally dynamic contents.
    • Leaning a little towards just making this work with a helper.
      • tslib?
        • Yes, but you might want this fixed (file extensions might not be recognized).
        • Well users can lock on a tslib.
  • This is in theory simple enough - so simple it could be a standalone tool. Which is an argument both for and against doing it.
    • People have written them, but they don't get the error checking.
  • Feels like we need answers for
    • moduleSuffixes
    • outDir
  • If people want to use these modes, they usually don't want to use tsc in the tight loop anyway, right? Why do people want to write tsc? Some other tool can do this rewriting.
    • Declaration files
  • How do you avoid the ../../src/foo.ts vs. ../../dist/foo.js problem?
    • Is it a problem? Doesn't work today if you reference the input file.
      • But that's the whole story - you're running off of input files. And the way people avoid thinking about this is imports/exports subpaths in package.json, workspaces, or path mappings.
    • Probably needs custom conditions and non-relative paths.
      • Though are there custom conditions that don't get triggered within node_modules? Because you don't want to resolve to the .ts files in node_modules (they'll fail at runtime!).
  • There are a LOT of issues regarding deployment, project structuring, scaling, etc. that need to be solved. Needs to fundamentally be built into how Node.js itself supports TypeScript.

DanielRosenwasser avatar Aug 20 '24 23:08 DanielRosenwasser

We probably should look at if JSR does the same transforms that we're looking to do.

From https://jsr.io/docs/publishing-packages#jsr-package-rules, it looks like JSR doesn’t support publishing code that references itself with package.json "imports" or self-name imports. I think files within each package have to reference each other with relative imports. @lucacasonato is that right?

andrewbranch avatar Aug 26 '24 18:08 andrewbranch

Currently yes. We are currently discussing whether it is useful to allow this though.

lucacasonato avatar Aug 26 '24 19:08 lucacasonato