Announcing TypeScript 7.1 Beta

Today we’re excited to announce the beta release of TypeScript 7.1!

npm install -D typescript@beta

Let’s take a look at what’s new in TypeScript 7.1!

Support for Import Attributes in Ambient Modules

Import attributes are metadata that are attached to import statements. Typically, they’re meant to instruct runtimes and bundlers on how to interpret the content of an import, as well as the shape of the resulting module. For example,

import myData from "./data/someData.json" with { type: "json" };

Everything in the object following the with keyword is an import attribute. Environments like browsers can’t simply decide how to deal with an import based on file name extensions like .json. Specifying type: "json" tells whatever runtime that someData.json needs to be interpreted as a JSON file, parsed out, and provided via a default import (in our example above, that’s myData).

The type attribute has become the de facto way for runtimes to customize this behavior. ECMAScript (JavaScript) has a proposal that allows code to specify type: "text", which returns the import’s contents as a string.

import readme from "../README.md" with { type: "text" };

console.log(readme);

There is also a proposal for type: "bytes" to return a Uint8Array of raw bytes.

import { pngToPixels, boxBlur } from "./photoUtils.js";

import photo from "./myPhoto.png" with { type: "bytes" };
const blurryPhoto = boxBlur(pngToPixels(photo));

Browsers have also allowed importing CSS files as CSSStyleSheets with type: "css" for a few years now.

import someTheme from "./themes/someCoolTheme.css" with { type: "css" };

document.adoptedStyleSheets.push(someTheme);

To support importing these files, people might use ambient module declarations in TypeScript using a wildcard pattern (e.g. *.css).

// You can write this in a global `.d.ts` file with no import statements.

declare module "*.css" {
    const content: CSSStyleSheet;
    export default content;
}

declare module "*.txt" {
    const content: string;
    export default content;
}

declare module "*.md" {
    const content: string;
    export default content;
}

declare module "*.bin" {
    const content: Uint8Array;
    export default content;
}

This is okay, but it doesn’t work for all environments as it doesn’t account for import attributes at all.

You might ask why this is an issue – at first glance, it seems like the only problem is that it just allows people to accidentally leave off an import attribute.

// ❌ oops, forgot an import attribute
import readme from "../README.md";

// ✅ what we were supposed to write
import readme from "../README.md" with { type: "text" };

But that is still a problem worth fixing. Another issue is that it becomes repetitive. With import attributes, the entire issue is that the runtime cares about the attributes, not the file extension. We shouldn’t have to re-declare a pattern for both .txt and .md files if both were going to use type: "text".

But a major issue is that runtime environments may support different import attributes entirely, and may act differently depending on whether they’re present. For example, bundlers might use a build-time feature called CSS Modules as the default behavior when importing .css files, but specifying the browser-supported type: "css" in the import statement will override this behavior and ensure the .css file is brought in as a CSSStyleSheet object.

That’s why TypeScript 7.1 introduces support for import attributes in ambient module declarations. You can now declare the following in your TypeScript projects, get an error if you try to import a file without the required import attributes, and get the correct type based on the import attributes.

declare module "*" with { type: "css" } {
    const content: CSSStyleSheet;
    export default content;
}

declare module "*" with { type: "text" } {
    const content: string;
    export default content;
}

declare module "*" with { type: "bytes" } {
    const content: Uint8Array;
    export default content;
}

Note that imports matching these declarations are not validated against files on disk. As is currently the behavior when an import matches an ambient module declaration, failed lookups will be reported at runtime or during a bundler’s build process.

Also note that these declarations are not shipped as part of the TypeScript built-in libraries. We recommend libraries not include them in their published packages, and end-users will need to declare them in their own projects if necessary. That will provide end-users with flexibility on how the global scope is configured (e.g. lib.dom.d.ts versus @types/node) and will prevent conflicts with built-in declarations in the future.

For more information, see our implementing pull request here.

(节选)

原文:TypeScript Blog|Announcing TypeScript 7.1 Beta,2026-10-21