CODE VERIFIED

A Word-Boundary Fix Helps Vite Find TypeScript Imports

Vite now distinguishes the word “type” from longer import names such as “typescript” during dependency scanning. The correction is small, but it prevents ordinary JavaScript imports from being mistaken for TypeScript-only declarations.

Sep 25, 2026, 3:19 am PDT · 4 min read
A magnifying lens distinguishes a whole token from a longer name in a dependency graph.
AI-generated editorial illustration; conceptual, not a screenshot.

Quick Answer

Vite now distinguishes the word “type” from longer import names such as “typescript” during dependency scanning. The correction is small, but it prevents ordinary JavaScript imports from being mistaken for TypeScript-only declarations.

In Plain English

A development server scans imports to learn which packages an application needs. A type-only import describes data for the compiler and does not load a runtime package. An imported variable named typescript, however, can represent real code. A text scanner must tell those cases apart.

Import statement; Check the complete type keyword; Capture the runtime package; typescript: runtime binding; typeorm: runtime binding; type: documented ambiguity
Source-based editorial infographic explaining the reviewed change. Not a benchmark or a live screenshot.

Code Evidence

In packages/vite/src/node/optimizer/scan.ts, the exclusion for import type gains a word boundary. The accompanying scan tests now check the extracted package name instead of expecting the same package in every example. Added cases cover default bindings named typescript, typeorm, and types.

Why the identifier matters

The distinction begins with the role of the imported name. In a statement such as import typescript from a package, typescript is a local binding chosen by the author. Its spelling does not make the import disappear from the running program. By contrast, import type signals a declaration intended for TypeScript's type system. A scanner that uses the first four letters as its decision point can confuse a valid runtime dependency with compiler-only information. The repair makes that decision depend on the boundary of the keyword. This is a lexical correction with a directly identifiable failure condition.

The examples added to the tests are useful because they vary that local name while preserving the behavior the scanner should recognize. Names such as typeorm and types demonstrate that the issue is a family of prefixes, rather than an exception for one popular package. Checking the actual extracted package also strengthens the assertion: a scanner should discover the source named in each statement, not merely produce a plausible-looking result. The test therefore addresses both classification and the content of the discovery result.

A realistic development scenario

Consider a team whose application imports a runtime library through a default binding named typescript. The code can be valid even if the initial dependency scan overlooks that statement. The developer may then see the dependency become visible only when the running application reaches it. That hypothetical sequence explains why discovery behavior deserves inspection even when the eventual import works. It does not establish that every delayed dependency is caused by this expression or that a missed initial scan necessarily breaks the page.

Renaming a binding could conceal this particular trigger, but that would leave the scanner's classification rule unchanged. A useful diagnosis records the exact import statement and the installed Vite version, then compares them with the regression examples. Package resolution, conditional imports, and plugin transformations remain separate questions. Keeping the original statement in a minimal reproduction makes it easier to determine whether the problem is discovery or a later stage of loading.

How to validate the change in your project

Start with a small entry point that imports the affected package under a name beginning with type and actually uses the imported value. Compare the development startup behavior before and after the relevant patch, keeping the package version, configuration, and entry point fixed. Include a genuine type-only import as a control so that the check covers the distinction the fix is meant to preserve. These are proposed verification steps; no such application run was performed for this article.

Observe whether the expected package is discovered and whether the application can use it, rather than reducing the outcome to a single startup-time number. A timing comparison can be distorted by caches and unrelated work. If the binding is exactly type, record that case separately because the source comments retain an ambiguity there. A successful check for typescript does not prove that all TypeScript syntax is fully parsed. The practical outcome to look for is correct treatment of the covered runtime imports while type-only declarations continue to be excluded.

Why It Matters

For teams debugging a dependency that appears only after the development server starts running the app, this patch supplies a concrete place to investigate. Our reading is that better initial discovery can reduce surprises in startup behavior; the diff does not establish a measured startup-speed improvement. It also illustrates why a valid identifier should not be classified solely by its prefix.

An Open Question

What happens when the default binding is literally named type? The new test comments explicitly retain that ambiguity. They say a missed dependency can still be discovered at runtime, so this is an incremental scanner correction rather than a complete JavaScript parser.

Scope and Limitations

We inspected the patch and its regression cases. We did not execute Vite or benchmark an application. The release notes list the fix in 8.3.1.

Sources