auto-import broken for runtime hooks (useModel/useIntl) due to `export *` chain in index.d.ts
Bug Description
When using umi, editor auto-import (VSCode built-in TypeScript language service) cannot auto-import runtime hooks like useModel, useIntl, useAccess, etc. from "umi". The user has to manually type import { useModel } from "umi" every time.
Type checking works fine -- this is purely an auto-import / IntelliSense issue.
Expected Behavior
Typing useModel or useIntl in a .tsx file should suggest auto-importing it from "umi".
Actual Behavior
Typing useModel shows no auto-import suggestion from "umi", or only suggests importing from @@/plugin-model / @@/plugin-locale (internal generated paths), not from the public "umi" entry.
Root Cause
The root cause is that index.d.ts uses two layers of wildcard re-export:
// node_modules/umi/index.d.ts
// @ts-ignore
export * from "@@/exports"; // layer 1: export *
export type { IApi, ... } from "@umijs/preset-umi";
export * from "./dist"; // layer 2: export *The VSCode / TypeScript auto-import engine does not recursively traverse export * chains to build its "symbol -> module" index. As a result:
useModelis exported from@@/plugin-model-> re-exported viaexport *in@@/exports.ts-> re-exported viaexport *inumi/index.d.ts- TypeScript type-checks this correctly (the types are resolved)
- But the auto-import engine cannot trace this 2-hop
export *chain back to"umi"
This is a known limitation of the TS language service's auto-import provider (see microsoft/TypeScript#43313). In umi's case the problem is amplified because the @@/exports target is a path-mapped, auto-generated file.
Current Workarounds (both have drawbacks)
1. Override tsconfig.json paths to point umi directly at .umi/exports.ts:
{
"compilerOptions": {
"paths": {
"umi": ["./src/.umi/exports.ts"]
}
}
}- [+] Fixes auto-import for runtime hooks
- [-] Loses build-time types (
IApi,IRoute,defineConfig,Service,run, etc.) from./node_modules/umi/distand@umijs/preset-umi. These are essential for plugin development (plugins/*.ts) andconfig.ts.
2. Point umi to a manually-maintained bridge file + node_modules:
{
"compilerOptions": {
"paths": {
"umi": ["./types/umi-bridge.d.ts", "./node_modules/umi"]
}
}
}with a bridge file that uses explicit named re-exports (which the auto-import engine can parse):
// types/umi-bridge.d.ts (manual maintenance required!)
export { useModel, Provider } from "@@/plugin-model";
export { useIntl, SelectLang, FormattedMessage } from "@@/plugin-locale";
// ... must manually sync with src/.umi/exports.ts every time umi regenerates it
export type { IApi, IRoute } from "@umijs/preset-umi";
export * from "umi/dist/service/service";- [+] Works for both auto-import and build-time types
- [-] Fragile and unmaintainable -- requires manual sync with the auto-generated
exports.ts.
Suggested Improvement
Consider generating the runtime exports in index.d.ts (or a sibling .d.ts) using explicit named re-exports instead of export *, so the TS auto-import engine can index them directly.
Since umi already generates src/.umi/exports.ts with full knowledge of all enabled plugins, the codegen could emit this explicit list into a type entry:
// node_modules/umi/index.d.ts (or generated sibling)
// Keep explicit named exports for runtime hooks -- auto-import friendly
export { defineApp } from "@@/core/defineApp";
export { Access, useAccess, useAccessMarkedRoutes } from "@@/plugin-access";
export { useAntdConfig, useAntdConfigSetter } from "@@/plugin-antd";
export { useIntl, SelectLang, FormattedMessage } from "@@/plugin-locale";
export { Provider, useModel } from "@@/plugin-model";
export { useRequest, request } from "@@/plugin-request";
export { history, Link, Outlet, useNavigate } from "@@/renderer-react";
// Build-time types still via export *
export type { IApi, IRoute, IUtoopackUserConfig } from "@umijs/preset-umi";
export * from "./dist";Environment
- umi version: 4.6.80
- OS: Windows 10
- Editor: VSCode (latest)
- tsconfig.json:
{
"extends": "./src/.umi/tsconfig.json",
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@@/*": ["./src/.umi/*"],
"umi": ["./node_modules/umi"],
"umi/typings": ["./src/.umi/typings"]
}
}
}Reproduction
npx create-umi@latest(React + antd + model + locale plugins)- Start dev server (
umi dev) sosrc/.umi/exports.tsis generated - Open any
.tsxfile, typeuseModeloruseIntl - Observe: no auto-import suggestion from
"umi"
Source: umijs/umi