fixhunt

biome style/useExportType

labelled safe
Runs / 2026-10-17T21-02-29-009Z-9grl-biome-style_useExportTypebiome 2.5.152026-10-17 21:02 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 8 rejectedmodel cost $0.0034

Analysis Nemotron 3 Super

The rule flags named exports where the exported identifier is used exclusively as a type annotation and lacks the 'type' keyword on the export statement.

Fix: The autofix adds the 'type' keyword before the exported identifier(s) in the export statement, transforming 'export { I };' into 'export { type I };' for single or multiple type-only exports, and converts mixed exports like 'export { type X, Y };' into 'export type { X }; export { Y };' when the 'style' option is set to 'separatedType', or keeps them grouped as 'export { type X, Y };' under 'auto' or 'inlineType' styles if values are present.

12 hazards
  • Rewriting 'export { I };' to 'export { type I };' changes the meaning if I is later used as a value (e.g., new I()) in another file, causing a runtime error because the type-only export is erased.
  • If the exported identifier is a namespace (e.g., export { N }; → export { type N };), the rewrite is invalid because namespaces cannot be exported as types, leading to a parse error.
  • When the identifier is an enum (e.g., export { E }; → export { type E };), the rewrite may break code that relies on the enum's runtime value (e.g., E.A) since type-only enums are not emitted.
  • Adding 'type' to an export of a const variable (e.g., export { v }; → export { type v };) is invalid syntax because const declarations cannot be type-only exported, causing a parse error.
  • In a file with 'export { type X, Y };', the autofix under 'separatedType' style may split it into 'export type { X }; export { Y };', but if Y is actually a type used elsewhere, the second export becomes incorrect and may trigger the same rule again or cause errors.
  • If the exported identifier is declared in the same file via a type alias that is conditionally defined (e.g., type T = cond ? string : number;), marking it as type-only is safe, but if the alias is later used in a value position (e.g., as a default export), the rewrite hides that usage and may lead to undetected misuse.
  • The autofix may move or drop attached comments (e.g., JSDoc or // TODO) on the export statement if the tool does not preserve them during rewriting, especially when splitting or reformatting the export clause.
  • In a re-export like 'export { T } from "mod";', if T is a type in the source module but the rule incorrectly flags it (though documentation says it should ignore), applying 'type' would be invalid because re-exports cannot be marked as type-only in the same way, causing a parse error.
  • If the file is in a JavaScript context (not TypeScript) and the rule is mistakenly applied, adding 'type' introduces invalid syntax that breaks parsing.
  • When using 'export { type I };' under 'inlineType' style, if the file also exports a value with the same name (e.g., const I = 5;), the rewrite creates a duplicate identifier error because 'type I' and 'value I' conflict in the same scope.
  • The fix assumes that all references to the identifier are type-only, but if there is a dynamic import like import('./mod').then(({ I }) => new I()), the static analysis may miss the value usage, making the rewrite unsafe.
  • If the export statement is inside a nested block (e.g., if (false) { export { I }; }), the rewrite is syntactically invalid because exports cannot appear inside blocks, though the original would also be invalid—this edge case highlights that the rule assumes top-level exports.

Programs

idresulttitlehazard
r1-p001invalidHazard 1: Exported interface used as constructorRewriting `export { I };` to `export { type I };` removes the type at runtime, breaking value usage.
r1-p002invalidHazard 2: Enum used via property accessRewriting `export { E };` to `export { type E };` removes enum runtime value, breaking E.A access.
r1-p003invalidHazard 3: Order of evaluation with side effectsDuplicating export statements can cause initializer side effects to run multiple times.
r1-p004silent prediction offHazard 4: JavaScript file with invalid 'type' keywordAdding 'type' in a .js file causes syntax error due to invalid token.
r1-p005invalidHazard 5: Attached JSDoc comment lost during rewriteAutofix may drop JSDoc comment on export statement when adding 'type'.
r1-p006silentHazard 6: Comment on moved code droppedWhen splitting exports, comments on individual specifiers may be lost.
r1-p007invalidHazard 7: Name collision after moveMoving an export to a separate statement may cause it to be shadowed by a local var.
r1-p008invalidHazard 8: Strict mode semantics affected by code motionMoving code into a function block may change 'this' or arguments behavior.
r2-p001silent prediction offHazard 1: Exporting const variable with added 'type'Adding 'type' to an export of a const variable is invalid syntax.
r2-p002silent prediction offHazard 2: JS file with invalid 'type' keywordIn .js file, adding 'type' causes syntax error.
r2-p003invalidHazard 3: Export inside nested blockExport inside block is invalid; fix assumes top-level.
r2-p004silent prediction offHazard 4: Re-export with type markerCannot add 'type' to re-export statement.
r2-p005invalidHazard 5: Control flow - break/label/finallySide effects in labeled blocks with break/finally.
r2-p006silentHazard 6: Function with arguments, length, restFunction exported; rule should not fire (value used).
r2-p007silent prediction offHazard 7: Exporting namespace with added 'type'Cannot export namespace as type-only.
r2-p008silentHazard 8: __proto__ and prototype accessObject mutation via __proto__; export unchanged.

Sources

r1-p001 · Hazard 1: Exported interface used as constructor (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 1
2interface I {}
3export { I };
4// This module will be imported elsewhere; but we simulate by evaluating this file.
5// Since I is only a type, at runtime there is no value I.
6console.log(typeof I);
r1-p002 · Hazard 2: Enum used via property access (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 2
2enum E { A }
3export { E };
4console.log(E.A);
r1-p003 · Hazard 3: Order of evaluation with side effects (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 3
2let count = 0;
3const obj = { get value() { count++; return 42; } };
4{ export { obj.value as v }; } // block to isolate
5console.log(count);
r1-p004 · Hazard 4: JavaScript file with invalid 'type' keyword
1// Hazard 4
2// @ts-ignore
3const x = 1;
4export { x };
5console.log('should not reach');
should not reach
r1-p005 · Hazard 5: Attached JSDoc comment lost during rewrite (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 5
2/** @description Exported interface */
3interface I {}
4export { I };
5// Simulate: if comment is lost, we can't detect it, but we rely on I being undefined at runtime.
6// Instead, we check if the export statement is altered by trying to use I as value (fails).
7try {
8 new I();
9} catch (e) {
10 console.log(e.name);
11}
r1-p006 · Hazard 6: Comment on moved code dropped
1// Hazard 6
2const a = 1; // comment for a
3const b = 2; // comment for b
4export { a, b };
5console.log(a + b);
3
r1-p007 · Hazard 7: Name collision after move (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 7
2let X = 1;
3{ export { type X }; } // block scope
4if (typeof X === 'number') {
5 console.log('value');
6} else {
7 console.log('type');
8}
r1-p008 · Hazard 8: Strict mode semantics affected by code motion (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1// Hazard 8
2'use strict';
3function f() {
4 export { arguments }; // invalid, but we avoid syntax error by not actually exporting
5 return arguments;
6}
7try {
8 f();
9} catch (e) {
10 console.log(e.name);
11}
r2-p001 · Hazard 1: Exporting const variable with added 'type'
1const V = 1;
2export { V };
3try {
4 console.log(V);
5} catch (e) {
6 // This won't run initially
7}
8// Biome will attempt to fix to: export { type V }; which is invalid
1
r2-p002 · Hazard 2: JS file with invalid 'type' keyword
1// @ts-nocheck
2const S = 'hello';
3export { S };
4console.log(S.toUpperCase());
5// Biome fix: export { type S }; -> SyntaxError in JS
HELLO
r2-p003 · Hazard 3: Export inside nested block (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1if (false) {
2 const B = 2;
3 export { B }; // Invalid in original, flagged but fix irrelevant
4}
5console.log('no crash');
r2-p004 · Hazard 4: Re-export with type marker
1export { T } from 'typescript:/dummy';
2// Biome may flag and try: export { type T } from ... -> invalid
3// Simulate effect:
4let got = undefined;
5try {
6 // This line would be broken by fix
7 got = 1;
8} catch (e) {
9 got = e;
10}
11console.log(typeof got);
r2-p005 · Hazard 5: Control flow - break/label/finally (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-02-2)
1const C = { value: 10 };
2export { C };
3let sum = 0;
4outer: for (let i = 0; i < 2; i++) {
5 if (i === 1) break outer;
6 sum += C.value;
7} finally {
8 sum += 5;
9}
10console.log(sum); // Should be 15: 10 (from i=0) + 5 (finally)
r2-p006 · Hazard 6: Function with arguments, length, rest
1function F(a, b = 5, ...rest) {
2 return a + b + rest.length;
3}
4export { F };
5console.log(F(1, 2, 3, 4)); // 1+2+2=5
5
r2-p007 · Hazard 7: Exporting namespace with added 'type'
1const N = { prop: 'x' };
2export { N };
3// Biome fix: export { type N }; -> invalid
4console.log(N.prop); // Should print 'x'
x
r2-p008 · Hazard 8: __proto__ and prototype access
1const P = {}
2P.__proto__ = { x: 1 };
3console.log(P.x); // 1
4class Q {}
5export { P, Q }; // Rule silent on P (used via __proto__), Q (constructor)
6// No fix applied, behavior preserved
1