跳到正文
DEV Community· Shivam Dwivedi·· 1 天前AI 評分40

TypeScript 7.1 可檢查 import 屬性,仍可能漏掉不存在的檔案

TypeScript 7.1 can check an import attribute and still miss a missing file

AI 導讀

TypeScript 7.1.0-beta 可按 ambient module declaration 檢查符合條件的 import,並為匯入內容提供相應型別,但不會確認目標檔案是否存在。即使編譯通過,缺少 missing.txt 仍會令輸出的 JavaScript 在 Node 22.22.1 執行時因 ERR_MODULE_NOT_FOUND 而失敗。

正文

My TypeScript 7.1 Beta example passed the compiler. The imported file did not exist. Running the emitted JavaScript failed with ERR_MODULE_NOT_FOUND.

That result is a useful way to understand the beta's new ambient module declarations: they describe how an import should be typed. They do not prove that its target exists. 💡

A matching text attribute passes; a missing or wrong attribute fails; an absent file still fails at runtime.

Results from my small compiler check using TypeScript 7.1.0-beta. The runtime failure deliberately uses a nonexistent file.

The new declaration follows the attribute

TypeScript's October 20 announcement adds import attributes to ambient module declarations. That lets a project describe a module selected by an attribute, instead of repeating declarations for every file extension. These declarations are supplied by the project; the beta does not add them to its built-in libraries. [1]

Here is the complete declaration I used in assets.d.ts:

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

And the import in good.ts:

import note from "./missing.txt" with { type: "text" };
const upper: string = note.toUpperCase();
console.log(upper);

The compiler accepts the import and treats note as a string. The deliberate filename is a clue to the next boundary. 🔍

Reproduce the compiler result

In an empty project with Node and npm available, install the exact beta I checked:

npm install --save-dev typescript@7.1.0-beta
npx tsc --ignoreConfig --module esnext --target es2022 --strict --noEmit assets.d.ts good.ts

I checked these cases with the same compiler options:

Import form Compiler result
with { type: "text" } Passed
Attribute omitted Failed
with { type: "bytes" } Failed

The declaration only supplies the text case. It gives the compiler no matching declaration for the other imports in this fixture. ✅

That makes the attribute useful at the development boundary: a project can require the import form its tooling expects, and code gets the corresponding type.

Now cross the runtime boundary

I emitted the accepted case with:

npx tsc --ignoreConfig --module esnext --target es2022 --strict --outDir dist assets.d.ts good.ts

With {"type":"module"} in dist/package.json, node dist/good.js failed because missing.txt was absent. The runtime check used Node 22.22.1. It does not demonstrate a working text-import implementation.

The compiler did exactly what the declaration asked: it gave the matching import a type. It did not find or create the file. Microsoft's announcement explicitly documents that ambient matches do not validate file lookups. [1]

⚠️ An ambient declaration is easy to mistake for a loader configuration. It supplies neither the asset nor the runtime behavior. Keep the build or runtime check that proves your real asset-loading route works.

Where I would use this

In a project whose bundler or runtime already supports attribute-based loading, I would describe that established behavior with a narrowly chosen declaration. Then I would run a small real import through the build as well as through the type checker.

For this fixture, the useful result is the boundary itself: the matching attribute gets checked, while file availability remains another tool's job. 🧪

References

  1. Microsoft: Announcing TypeScript 7.1 Beta, October 20, 2026.

Asset credit: original diagram generated from the saved compiler outcomes. No speed benchmark or production compatibility claim.

AI disclosure

AI was used to draft the article.

來源:DEV Community · dev.to