Flow: Reason for error: "Cannot import the type `[type]` as a value. Use `import type` instead"?

Created on 11 Jul 2018  路  5Comments  路  Source: facebook/flow

Since Flow v.0.75.0, this triggers an error:

// model.js
export type TypeA = string;
import * as model from './model';

// ERROR: Cannot import the type `TypeA` as a value. Use `import type` instead.
const { TypeA } = model;

const someVar1: TypeA = 'test';
// $ExpectError Type checking still works, despite error when destructuring model
const someVar2: TypeA = 1;



md5-1855fe7093a174eff1c7d4ef7e5fb835



import * as model from './model';

const someVar1: model.TypeA = 'test';
const someVar2: model.TypeA = 1; // $ExpectError

It seems strange to me that the former example triggers an error, while the latter doesn't, since I'm pretty sure (correct me if I'm wrong) they do the exact same thing and the only difference is a stylistic one.

I personally like to destructure model imports like in the first example, since in practice the model files will contain a lot of flow types (as well as non-flowtype stuff). Importing them all separately using import and import type causes a lot of clutter in the imports section of files because it won't all fit on a single line, which makes the imports of a file much more difficult to read at first glance. Of course I can avoid the error by prefixing all types with model. like in the second example, but that's less than ideal since it results in more typing / longer lines of code / less readability, for no appearant reason.

I went trough the commit history in an attempt to find the reason for this change and I think this is the relevant commit? In the commit message it says:

This is not a useful pattern since T cannot be used as a value in B.js. Sure enough
any potential use would result in an error further down the line, but it's good practice to
hint to the actual source of the error which is the import itself.

However, that doesn't take into consideration that when using this pattern, the types can still be used as Flow types, and like it says in the commit message, if you attempt to use them as values it still causes an error down the line so there is no risk of a problem going unnoticed.

So now I'm wondering if I missed something? If so, can someone explain why the first example is a problem (and why the second example isn't)? Thank you in advance!

not a bug

Most helpful comment

This is working as intended. Use import type to import a type.

All 5 comments

What do you do here?

const { TypeA } = model;

You create a JS variable with value... With what value, really? A variable can't contain a type as a value.

I think the closest thing to what you're looking for that makes sense semantically would be adding support to Flow for something like

type { TypeA } = model;

But like @apsavin says, you're currently destructuring a type into a value (const), which doesn't make sense.

Yeah, I agree that the syntax proposed by @jamesisaac would make a lot more sense, but since Flow doesn't support that atm and using const actually does work, I've been using that for now. (Although usually it looks more like const { namedExportA, namedExportB, TypeA, TypeB } = model, since model files don't only contain types.)

ETA: The main purpose is to not have to import all of the types / other named exports separately, since it clutters up the imports section. I haven't found a better way to do that yet, which is why I've been using the pattern described above.

This is working as intended. Use import type to import a type.

change import { MyType } from '../../flow' to => import type { MyType } from '../../flow'

Was this page helpful?
0 / 5 - 0 ratings