Skip to content

Ambient Module Declarations for Import Attributes (formerly known as Import Assertions)Β #46135

Open
@haoqunjiang

Description

@haoqunjiang

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:

  1. 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.
  2. 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

  1. The abovementioned frontend build tools.
  2. Type definitions for browsers' built-in CSS & JSON modules support. We can have declare module '*' assert {type: 'json'} and declare module '*' assert {type: 'css'} in the DOM lib.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions