Skip to content

Auto-import will always use the first import instead of looking for the first import of the correct kindΒ #53008

@bradzacher

Description

@bradzacher

Bug Report

πŸ”Ž Search Terms

auto import type-only value

πŸ•— Version & Regression Information

  • This is the behaviour in every version I tried

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

import type { ComponentType } from 'react';
import { useState } from 'react';

export function Component({ prop } : { prop: ComponentType }) {
  const codeIsUnimportant = useState(1);

  // trigger auto-import for this line
  useEffect(() => {}, []);
}

πŸ™‚ Expected behaviour

When I trigger auto-import for the useEffect function, TS should look at all of the imports and find the first value import declaration with the correct source to use.
I.e. I would expect this result:

import type { ComponentType } from 'react';
import { useState, useEffect } from 'react';

πŸ™ Actual behaviour

When I trigger auto-import for the useEffect function, TS looks for the first import declaration with the correct source, even if it's a type-only import. If it is type-only, TS will remove the qualifier entirely.

I.e. it results in this code

import { ComponentType, useEffect } from 'react';
import { useState } from 'react';

Which is pretty bad because it means TS changes the meaning of the code for some compilers!

If 5.0's verbatimModuleSyntax is turned on, then instead you get this:

import { useEffect, type ComponentType } from 'react';
import { useState } from 'react';

Which is marginally better as it at least preserves the meaning of the code.


Note that the same thing happens if you reverse the situation.
playground

import { useState } from 'react';
import type { ComponentType } from 'react';

export function Component({ prop } : { prop: ComponentType }) {
  const codeIsUnimportant = useState(1);

  // trigger auto-import for this line
  type T = InvalidEvent;
}

By default TS will insert the type import in the value import:

import { InvalidEvent, useState } from 'react';
import type { ComponentType } from 'react';

If 5.0's verbatimModuleSyntax is turned on, then instead you get this:

import { type InvalidEvent, useState } from 'react';
import type { ComponentType } from 'react';

Suggested change:

  • When auto-importing, gather all of the import declaratinos.
  • If the imported thing is a type, then prefer using the first type-only import declaration.
  • If the imported thing is a value, then prefer using the first value import declaration.
  • If there is no matching declaration, then I think one of the following should occur:
    • If the thing is a value and the only import declarations are type-only, then insert a new value import declaration. DO NOT mutate the existing import declaration(s) to remove the top-level type-only qualifier.
    • If the thing is a type and the only import declarations are value, then one of the following should occur (perhaps configurably?):
      • Insert a new specifier into the value declaration, qualifying the specifier with type
      • Insert a new type-only import declaration.

The most important bit, IMO, is that TS should NEVER remove the top-level type qualifier from an import when performing an auto-import.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions