Repository: TypeScript
Issue: Support resolving types from import specifiers using custom schemes
Labels: Suggestion,In Discussion

# 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:

* [X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [X] This wouldn't change the runtime behavior of existing JavaScript code
* [X] This could be implemented without emitting different JS based on the types of the expressions
* [X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [X] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).

## ⭐ 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 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?

```json
{
  "compilerOptions": {
    "paths": {
      "example:*": "*"
    }
  }
}
```

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 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.