Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: tsconfig option "conditions=x,x,x," "exportConditions" with moduleResolve: node<any> and nodenext and or importMap support #47931

Closed
5 tasks done
frank-dspeed opened this issue Feb 17, 2022 · 1 comment · Fixed by #51669
Labels
Experience Enhancement Noncontroversial enhancements Fix Available A PR has been opened for this issue Suggestion An idea for TypeScript

Comments

@frank-dspeed
Copy link

frank-dspeed commented Feb 17, 2022

Suggestion Okt 2022

We need a tsconfig setting that works 1:1 like the nodejs cli flag --condition or --conditions or the rollup exportCondition

Suggestion short

add a tsconfig option that gets used when node module resolution is used that hornors exports of the package json higher as current nodejs does and so use that if it exists.

the new config option should be named exportConditions to algin with other packages in the ecosystem.

it defines as string the value of the exports: fild in the package.json that should get used as environment indicator similar to the nodejs Implementation.

also a resolve algo called importMap could be added using the same exportConditions option with a combined importMap: options property be aware that this should never get a list by design only 1 single authoritativ map also the same for the package.json the one in the root project is authoritativ its exports: get used for every sub path. this is a Importent Concept in NodeJS.

Suggestion

We need a way to define which target environment to use with node12 and nodenext resolve algos which got introduced by ts4.5+. This could also get transformed to add importMaps support as the package.json got designed with importMaps in mind the futures should have the same syntax so that you can move fast foward later.

Maybe this issue is more well named: Support Conditional Exports in package.json when node12 + resolve algos are used?

the imports and exports fields of the package json do contain environment specific exports and imports i guess the default implementation now will use when require is used the require fild of the exports map of the imported module.

but when i for example want to require in a different environment i could also give there a sub tree with that environment name.

at last that is the design behind that. Now typescript got no clear target Environment definition in its tsconfig the target is always a module type. The Environment gets composed out of libs like ESNext Dom and so on.

exportConditions: ["string", "graalvm", "./"] // defines the resolve environment used default require import sub filds of exports and imports 
// dependent on code if defined "GraalVM" GraalVM fild gets used if supplyed else import require default.

🔍 Search Terms

List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily and help provide feedback.

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

A new config setting to define the default environment or filds exportConditions to use when node12 or nodenext resolve mode is used

📃 Motivating Example

Conditional Exports based on Environment that imports or exports stuff from a package.json as designed by the NodeJS Community aka import maps

💻 Use Cases

Create Multiple tsconfig files and build them to create diffrent js output for diffrent target environments based on package.json importMaps
package.json https://nodejs.org/api/packages.html#conditional-exports

// package.json
{
  "main": "./main-require.cjs",
  "exports": {
    "node": "./main-module.js",
    "graalvm": "./main-graaljs.js",
    "browser": "./main-browser.js",
    "default": "./main-module.js"
  },
  "type": "module"
}

the importent part is graalvm browser and default support this are the so called targetNodeResolve Environments. i have no clear name for that at present but it is in the spec and main design to have diffrent environments listed there in the package.json until final importMaps Implementation arrives in NodeJS then the syntax should be 1:1 translate able.

so maybe consider new resolve algo importMap.?!?

Node.js implements the following conditions, listed in order from most specific to least specific as conditions should be defined:

  • "node-addons" - similar to "node" and matches for any Node.js environment. This condition can be used to provide an entry point which uses native C++ addons as opposed to an entry point which is more universal and doesn't rely on native addons. This condition can be disabled via the --no-addons flag.
  • "node" - matches for any Node.js environment. Can be a CommonJS or ES module file. In most cases explicitly calling out the Node.js platform is not necessary.
  • "import" - matches when the package is loaded via import or import(), or via any top-level import or resolve operation by the ECMAScript module loader. Applies regardless of the module format of the target file. Always mutually exclusive with "require".
  • "require" - matches when the package is loaded via require(). The referenced file should be loadable with require() although the condition matches regardless of the module format of the target file. Expected formats include CommonJS, JSON, and native addons but not ES modules as require() doesn't support them. Always mutually exclusive with "import".
  • "default" - the generic fallback that always matches. Can be a CommonJS or ES module file. This condition should always come last.

Within the "exports" object, key order is significant. During condition matching, earlier entries have higher priority and take precedence over later entries. The general rule is that conditions should be from most specific to least specific in object order.

Using the "import" and "require" conditions can lead to some hazards, which are further explained in the dual CommonJS/ES module packages section.

The "node-addons" condition can be used to provide an entry point which uses native C++ addons. However, this condition can be disabled via the --no-addons flag. When using "node-addons", it's recommended to treat "default" as an enhancement that provides a more universal entry point, e.g. using WebAssembly instead of a native addon.

Conditional exports can also be extended to exports subpaths, for example:

{
  "main": "./main.js",
  "exports": {
    ".": "./main.js",
    "./feature": {
      "node": "./feature-node.js",
      "default": "./feature.js"
    }
  }
}

References

Imported undocumented or only partial documented in NodeJS ECMAScript docs

there is a specification score for the imports it defines which rule gets used it does that via ranking the most specific condition first then going to the less specific conditions.

@frank-dspeed frank-dspeed changed the title Typescript 4.5+: Feature Request: We need a way to define which target environment to use with node12 and nodenext Typescript 4.5+: Feature Request: define which target environment to use with node12 and nodenext resolve or add importMap support Feb 17, 2022
@frank-dspeed frank-dspeed changed the title Typescript 4.5+: Feature Request: define which target environment to use with node12 and nodenext resolve or add importMap support Typescript 4.5+: Feature Request: extra Config option "exportConditions" for node12 and nodenext resolve or add importMap support Feb 20, 2022
@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Feb 23, 2022
@frank-dspeed frank-dspeed changed the title Typescript 4.5+: Feature Request: extra Config option "exportConditions" for node12 and nodenext resolve or add importMap support Feature Request: tsconfig option "exportConditions" with moduleResolve: node<any> and nodenext and or importMap support Sep 8, 2022
@frank-dspeed
Copy link
Author

Little update it got now more real then before:

I just want to give a little update:

@frank-dspeed frank-dspeed changed the title Feature Request: tsconfig option "exportConditions" with moduleResolve: node<any> and nodenext and or importMap support Feature Request: tsconfig option "conditions=x,x,x," "exportConditions" with moduleResolve: node<any> and nodenext and or importMap support Oct 7, 2022
@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Dec 13, 2022
@andrewbranch andrewbranch added this to the TypeScript 5.0.0 milestone Dec 13, 2022
@andrewbranch andrewbranch added Experience Enhancement Noncontroversial enhancements and removed Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Dec 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experience Enhancement Noncontroversial enhancements Fix Available A PR has been opened for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants