Description
Suggestion
π Search Terms
import attributes, import assertions, ambient module
β 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
Following the suggestion at #40694 (comment)
Allow projects to declare ambient modules based on the import attributes. Such as:
declare module '*' with {type: 'css'} {
const stylesheet: CSSStyleSheet;
export default stylesheet;
}
π Motivating Example
Currently frontend build tools use file extensions and URL query strings to support all kinds of custom modules that are eventually compiled into JavaScript.
For example, in Vite (webpack supports these features in a similar way), we support JS modules importing .module.css
files as CSS modules, and adding ?url
postfixes to the imported path means we are to import the asset's real URL after bundling.
That is:
// get the exported classes from a CSS module
import classes from './example.module.css'
// Explicitly load assets as URL
import assetAsURL from './asset.js?url'
But:
- The extension approach may collide with new browser native features, such as the native CSS modules. So it's better to have a way to differentiate them. Import attributes could help in this case.
- The query string approach is not a standard.
- It alters the standard semantics of an import statement
- Different tools vary on their choices of queries
- Modules with such syntaxes won't be able to run separately without the specific bundler
- So, we hope to migrate away from this approach and base the feature upon a standard. Import attributes seems to be the way to go.
One thing that blocks us from doing so is the ability to declare ambient modules based on import assertions in TypeScript.
We can easily have type definitions for files based on their file extensions and query strings. In vite we have: https://github.com/vitejs/vite/blob/b690810f555549e9eed4b03600b27fe7649d6b07/packages/vite/client.d.ts
But currently, I don't see a way to migrate these type definitions when we move to import assertions.
π» Use Cases
- The abovementioned frontend build tools.
- Type definitions for browsers' built-in CSS & JSON modules support. We can have
declare module '*' assert {type: 'json'}
anddeclare module '*' assert {type: 'css'}
in the DOM lib.