You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I can fully appreciate the complexities in type resolution, so applying more things on top is likely... undesired, but thought I'd present this anyways just in case.
In some environments, especially Rollup, it is common to use custom import schemes (import ... from 'example:...') to denote modules that should use a specialized loader (Webpack before v5 used to similarly recommend 'example!...', but that looks to have gone out of fashion). Unfortunately, if these modules do not share a common interface, it is quite difficult to support this in TypeScript, as, as best as I can tell, it would require generating .d.ts entries for every single module.
This is a type resolution-only issue, the built output should not be altered at all.
🔍 Search Terms
import schema scheme protocol
✅ 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.)
Depending on the specifics of supported schemes already (such as node:), perhaps it's possible to allow some method of simply ignoring the scheme? So that example:<anything> resolves to <anything>; node:fs could resolve types from fs, and example:./myModule could resolve from ./myModule. This is likely to introduce issues in the future, however, if Node (or any other equivalent) introduces something that mandates a schema, so probably not viable.
Alternatively, perhaps the paths option could be altered to support this, including some way of using relative specifiers without resolving against baseUrl. This should follow standard relative import semantics, just ignore the scheme. I'm not quite sure what that would look like, though I suppose the following probably isn't breaking, as it is not allowed at the moment?
It will allow for TS to support transparent loaders that have become commonplace in many bundler ecosystems. It can replace a good deal of code gen when dealing with file types that TS can retrieve types from directly.
💻 Use Cases
Use: In an ideal world, I could (maybe alongside some configuration) write import { something } from 'example:./myModule'; and have TS correctly retrieve the types for something from myModule directly (if it can), without needing to create a declaration file/entry. This allows me to specify custom loaders that should be used on these modules without giving up TypeScript support.
Shortcomings: TS is simply not supported whilst doing this at the moment. While you could generate .d.ts files/entries for each module, this is simply not viable in my experience and is way too much overhead. Potential type issues at the module boundary are cheaper than TS appeasement.
Workarounds: None that are viable long-term, in my experience.
The text was updated successfully, but these errors were encountered:
In some environments, especially Rollup, it is common to use custom import schemes
I can't find any mention of "schemes" on the Rollup docs. What kind of values of example are common? Can you provide some links for context? I'm familiar with node:name for importing node built-in modules but haven't seen this syntax used for other things.
I can't find any mention of "schemes" on the Rollup docs.
Sorry, I'm not referring to Rollup itself here, but the ecosystem. Rollup won't even resolve from node_modules out-of-the-box, it's kept rather lightweight (and unopinionated).
The main similarity is that all of these are used in situations where there are consistent types; a generated URL is always a string, blog posts always have a certain type shape, etc. The only thing stopping one from using this pattern with modules that don't have a consistent typing is the type resolution. To some extent this can be "fixed" with code-gen, which some tools do use, but this can be a bit slow and overbearing.
My particular use case at the moment is implementing an "Islands" loader for Rollup -- basically signaling that certain (JSX) components need to be transformed a certain way. Unfortunately, I have to break the pattern and switch to signaling via file name (foo.island.js) instead of the preferred import protocol/scheme that matches everything else in the project (island:./foo.js). As these are (JSX) components, they certainly could benefit from TS providing hints to the type of props a component takes, but they do not share any common interface.
A more concrete example could look like this:
import{MyIsland,OtherExport,ATypeAliasMaybe}from'island:./MyIsland';constApp=()=><MyIsland/>;// What props does this take? TS won't be able to help here.
Suggestion
I can fully appreciate the complexities in type resolution, so applying more things on top is likely... undesired, but thought I'd present this anyways just in case.
In some environments, especially Rollup, it is common to use custom import schemes (
import ... from 'example:...'
) to denote modules that should use a specialized loader (Webpack before v5 used to similarly recommend'example!...'
, but that looks to have gone out of fashion). Unfortunately, if these modules do not share a common interface, it is quite difficult to support this in TypeScript, as, as best as I can tell, it would require generating.d.ts
entries for every single module.This is a type resolution-only issue, the built output should not be altered at all.
🔍 Search Terms
import schema scheme protocol
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
Depending on the specifics of supported schemes already (such as
node:
), perhaps it's possible to allow some method of simply ignoring the scheme? So thatexample:<anything>
resolves to<anything>
;node:fs
could resolve types fromfs
, andexample:./myModule
could resolve from./myModule
. This is likely to introduce issues in the future, however, if Node (or any other equivalent) introduces something that mandates a schema, so probably not viable.Alternatively, perhaps the
paths
option could be altered to support this, including some way of using relative specifiers without resolving againstbaseUrl
. This should follow standard relative import semantics, just ignore the scheme. I'm not quite sure what that would look like, though I suppose the following probably isn't breaking, as it is not allowed at the moment?Very much open to ideas/suggestions.
📃 Motivating Example
It will allow for TS to support transparent loaders that have become commonplace in many bundler ecosystems. It can replace a good deal of code gen when dealing with file types that TS can retrieve types from directly.
💻 Use Cases
Use: In an ideal world, I could (maybe alongside some configuration) write
import { something } from 'example:./myModule';
and have TS correctly retrieve the types forsomething
frommyModule
directly (if it can), without needing to create a declaration file/entry. This allows me to specify custom loaders that should be used on these modules without giving up TypeScript support.Shortcomings: TS is simply not supported whilst doing this at the moment. While you could generate
.d.ts
files/entries for each module, this is simply not viable in my experience and is way too much overhead. Potential type issues at the module boundary are cheaper than TS appeasement.Workarounds: None that are viable long-term, in my experience.
The text was updated successfully, but these errors were encountered: