Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency cycle detected import/no-cycle #2061

Closed
tcastelly opened this issue May 14, 2021 · 8 comments
Closed

Dependency cycle detected import/no-cycle #2061

tcastelly opened this issue May 14, 2021 · 8 comments

Comments

@tcastelly
Copy link

Hello,

After an update from '2.22.1' to '2.23.0' I have this error

Dependency cycle detected import/no-cycle

I'm trying to import a TypeScript Type like this:

./Bar.ts

import useBar from './useBar';

export type Bar = {
  msg: string
}

./useBar.ts

import type { Bar } from './Bar';

Previously import type even if it was cycled import worked.

@ljharb
Copy link
Member

ljharb commented May 14, 2021

That is indeed a dependency cycle, so it's a bug that it wasn't warning on it before.

@tcastelly
Copy link
Author

Was really a bug before?
According to this issue, #1453 I thought because we can import type with

import type from { ... }

it was allowed.

Anyway, thank you for your answer.

@ljharb
Copy link
Member

ljharb commented May 14, 2021

No, anything that causes two files to depend on each other is a cycle, and is a horrifically bad architecture, which is the purpose of the rule to prevent.

@raycharius
Copy link

Sorry, @ljharb, but this is wrong. The purpose of this rule is to avoid possible issues at runtime with circular dependencies. Using import type will never lead to that. Moreover, I disagree about this always being bad architecture when it comes to importing types. There are plenty of cases when this is more than appropriate.

At the very least, it should be configurable to exclude import type.

The makers of Madge know and understand that.

In any case, this has rendered this check useless for me because of this, which is actually really unfortunate. So, turning this rule off and integrating Madge into CI flow.

@ljharb
Copy link
Member

ljharb commented May 16, 2021

I agree that there’s a difference between avoiding runtime and build time cycles, and I’d be fine adding an option that allows type cycles.

However, import type can absolutely lead to that because enums and classes are in both value and type space.

@raycharius
Copy link

An option would be great – I would love to have this rule included. And I have a feeling that this has broken eslint for a lot of people ❤️

As for import type creating runtime issues, it won't, even with enums and classes, though using import with an enum will. I've created a small test repo that demonstrates this here.

In the documentation for import type, they say:

import type only imports declarations to be used for type annotations and declarations. It always gets fully erased, so there’s no remnant of it at runtime. Similarly, export type only provides an export that can be used for type contexts, and is also erased from TypeScript’s output.

However, there is a very poorly worded section:

It’s important to note that classes have a value at runtime and a type at design-time, and the use is context-sensitive. When using import type to import a class, you can’t do things like extend from it.

It can lead to the impression that import type will have a value at runtime, but looking at the example below, it's about the inability to extend the class as you would with an interface using import type.

If you're good with a flag, I'm happy to take a look and send over a pull request

@gabts
Copy link

gabts commented May 17, 2021

I agree a flag would be nice, TypeScript already yells at me if I try to use imported type as value.

Screenshot 2021-05-17 at 16 00 00

@quvide
Copy link

quvide commented May 19, 2021

As @raycharius commented, this definitely is a breaking change for many projects since the rule now flags a recommended pattern in Redux where the root state type is inferred by TypeScript from imported reducers.

You can safely import the RootState type from the store file here. It's a circular import, but the TypeScript compiler can correctly handle that for types. This may be needed for use cases like writing selector functions.


EDIT: This has apparently been fixed earlier today by #2083.

Thanks for the fix, @cherryblossom000! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants