microsoft / microsoft/TypeScript

Module resolution: ambient JSON wildcard module doesn't override `resolveJsonModule` typing

未关闭
#62,924 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Awaiting More Feedback Suggestion
主要语言
Go
星标
111k
派生
14.3k
平均合并
2 天 4 小时
30 天内合并 PR
132

描述

Demo Repo

https://github.com/niedzielski/2025-12-23-tsc-resolve-json-ambient-wildcard

Which of the following problems are you reporting?

The module specifier resolves to the right file, but something about the types are wrong

Demonstrate the defect described above with a code sample.

When resolveJsonModule is set, the imported JSON file's typing is used instead of the ambient module typing.

// schema-decl.d.ts
declare module '*.schema.json' {
  const json: import("./schema.js").Schema
  export default json
}
// index.ts
// Typed as JSON interpretation from file instead of ambient module.
import schemaJSON from './instance.schema.json' with { type: 'json' }
// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "noEmit": true
  }
}
Run tsc --showConfig and paste its output here
{
    "compilerOptions": {
        "module": "esnext",
        "moduleResolution": "bundler",
        "resolveJsonModule": true,
        "noEmit": true,
        "allowSyntheticDefaultImports": true,
        "resolvePackageJsonExports": true,
        "resolvePackageJsonImports": true
    },
    "files": [
        "./index.ts",
        "./schema-decl.d.ts",
        "./schema.ts"
    ]
}
Run tsc --traceResolution and paste its output here
======== Resolving module './instance.schema.json' from '/home/user/desk/foo/index.ts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
Loading module as file / folder, candidate module location '/home/user/desk/foo/instance.schema.json', target file types: TypeScript, JavaScript, Declaration, JSON.
File name '/home/user/desk/foo/instance.schema.json' has a '.json' extension - stripping it.
File '/home/user/desk/foo/instance.schema.d.json.ts' does not exist.
File '/home/user/desk/foo/instance.schema.json' exists - use it as a name resolution result.
======== Module name './instance.schema.json' was successfully resolved to '/home/user/desk/foo/instance.schema.json'. ========
======== Resolving module './schema' from '/home/user/desk/foo/index.ts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
Loading module as file / folder, candidate module location '/home/user/desk/foo/schema', target file types: TypeScript, JavaScript, Declaration, JSON.
File '/home/user/desk/foo/schema.ts' exists - use it as a name resolution result.
======== Module name './schema' was successfully resolved to '/home/user/desk/foo/schema.ts'. ========
======== Resolving module './schema.js' from '/home/user/desk/foo/schema-decl.d.ts'. ========
Explicitly specified module resolution kind: 'Bundler'.
Resolving in CJS mode with conditions 'import', 'types'.
Loading module as file / folder, candidate module location '/home/user/desk/foo/schema.js', target file types: TypeScript, JavaScript, Declaration, JSON.
File name '/home/user/desk/foo/schema.js' has a '.js' extension - stripping it.
File '/home/user/desk/foo/schema.ts' exists - use it as a name resolution result.
======== Module name './schema.js' was successfully resolved to '/home/user/desk/foo/schema.ts'. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist.
Found 'package.json' at '/home/user/desk/foo/node_modules/typescript/package.json'.
======== Resolving module '@typescript/lib-es5' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-es5'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-es5'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-es5'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-es5'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-es5'
Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-es5' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
======== Resolving module '@typescript/lib-decorators' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators'
Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-decorators' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
======== Resolving module '@typescript/lib-decorators/legacy' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators/legacy'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators/legacy'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators/legacy'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators/legacy'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-decorators/legacy'
Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
======== Resolving module '@typescript/lib-dom' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-dom'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-dom'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-dom'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-dom'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-dom'
Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-dom' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
======== Resolving module '@typescript/lib-webworker/importscripts' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-webworker/importscripts'
Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
======== Resolving module '@typescript/lib-scripthost' from '/home/user/desk/foo/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========
Explicitly specified module resolution kind: 'Node10'.
Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, Declaration.
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
Directory '/home/user/desk/foo/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-scripthost'
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-scripthost'
Directory '/home/user/node_modules/@types' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-scripthost'
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-scripthost'
Directory '/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'typescript__lib-scripthost'
Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: JavaScript.
Searching all ancestor node_modules directories for fallback extensions: JavaScript.
Directory '/home/user/desk/node_modules' does not exist, skipping all lookups in it.
Directory '/home/node_modules' does not exist, skipping all lookups in it.
Directory '/node_modules' does not exist, skipping all lookups in it.
======== Module name '@typescript/lib-scripthost' was not resolved. ========
File '/home/user/desk/foo/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/home/user/desk/foo/node_modules/typescript/package.json' exists according to earlier cached lookups.
index.ts:4:14 - error TS2322: Type '{ name: string; type: string; }' is not assignable to type 'Schema'.
  Types of property 'type' are incompatible.
    Type 'string' is not assignable to type '"File" | "Folder"'.

4 export const schema: Schema = schemaJSON
               ~~~~~~

Found 1 error in index.ts:4

Paste the package.json of the importing module, if it exists
{
  "name": "foo",
  "version": "0.0.0",
  "main": "index.js",
  "scripts": {
    "test": "npx tsc"
  },
  "keywords": [],
  "author": "Stephen Niedzielski <stephen@oidoid.com> (https://oidoid.com/)",
  "license": "AGPL-3.0-only",
  "description": "",
  "devDependencies": {
    "typescript": "5.9.3"
  }
}
Paste the package.json of the target module, if it exists

Same as importing module.

Any other comments can go here

Overriding JSON typing is an important feature for custom schemas. The workarounds now are:

  1. Cast.
  2. Use a non-JSON extension. For example, *.jsonc works.
  3. Disable resolveJsonModule.
  4. Instead of a wildcard, hardcode the module declarations to specific files.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从链接的演示仓库开始,然后运行提供的 tsc 配置和解析跟踪,以比较 schema-decl.d.ts 的 ambient 类型声明与 resolveJsonModule 对 index.ts 的行为。完成的标准是:导入的 JSON 遵循 ambient 通配符声明的 Schema 类型,同时模块解析仍能找到正确的文件。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript, typescript
领域
compilers
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。