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

a way to type libraries that may run in either nodejs or the browser #53308

Closed
5 tasks done
DetachHead opened this issue Mar 17, 2023 · 2 comments
Closed
5 tasks done
Labels
Duplicate An existing issue was already created

Comments

@DetachHead
Copy link
Contributor

DetachHead commented Mar 17, 2023

Suggestion

πŸ” Search Terms

node or browser types

βœ… 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

i have a library that could either be run in nodejs or the browser. this means i don't want any global types to be available that are not present in both the nodejs and browser runtimes.

πŸ“ƒ Motivating Example

with only the dom types:

window // no error
process // error (only available in node)
setTimeout // no error (available in both node and browser)

with only node types:

window // error (only available in browser)
process // no error
setTimeout // no error (available in both node and browser)

basically i would like to define sort of a "union" of the browser and node types, so that i get an error when attempting to access something that's not available in both environments.

πŸ’» Use Cases

  • when developing a library that supports both browsers and nodejs
@Andarist
Copy link
Contributor

It requires some setup but you can achieve this today with package.json#imports. You can isolate your env-specific things in per-environment files and import them using a single source, like:

import { foo } from '#isomorphic_foo'

and a package.json like:

{
  "isomorphic_foo": {
    "browser": "./browser_foo.js",
    "node": "./node_foo.js"
  }
}

Using this technique you could run tsc multiple times, with different customConditions, to validate correctness. The tricky part though is that you would probably have to rewrite this field before publishing. In your local setup, those should point to your .ts files while in the published package those should point to .js files. On top of that... you'd have to ensure that both "setups" (local and published ones) can load the types for those correctly. Alternatively, instead of rewriting package.json content before publishing you could locally use an additional source condition and "route" resolution to node/browser through it.

What I want to say is that it's possible today but quite involved and complicated 😬

@RyanCavanaugh
Copy link
Member

We've tried to handle this a bunch of times and come up short of a useful solution every time. The problem isn't just intersection, it's that you need to be able to handle cases where e.g. a certain value is of type string in one environment and number in another.

Duplicates at #31894, #37053, #52433, etc

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 17, 2023
@DetachHead DetachHead closed this as not planned Won't fix, can't repro, duplicate, stale Mar 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants