flow icon indicating copy to clipboard operation
flow copied to clipboard

Allow top-level library imports in declaration files

Open bluepnume opened this issue 4 years ago • 4 comments

Proposal

Allow declaration files to import types from other modules.

Use case

I have a use-case where I want to declare a type as a global var, but the type is re-used across my module.

types.js:

export type FooType = {|
    bar : number,
    baz : string
|};

declarations.js:

import { FooType } from './types.js';

declare var __FOO__ : FooType;

I would rather not have to copy-and-paste the type into declarations.js in order to declare it as a global. I would rather keep it in types.js and import it everywhere it is needed. I need to be able to declare it as a global for use with WebPack's DefinePlugin which can be used to define globals which are inlined at build time.

This used to work but in recent flow versions it throws the following error:

Cannot use an import statement at the toplevel of a library file. Import statements may only appear inside a
declare module. [toplevel-library-import]

Is it possible for the original behavior to be re-instated? Or is there an alternative way to declare globals based on imported types?

bluepnume avatar Jul 15 '21 19:07 bluepnume

we run into this in our builtin libs as well.

For example, in Node process is a global of type Process.

Process extends EventEmitter from the events module, which we have to type as the global events$EventEmitter, and then declare class EventEmitter extends events$EventEmitter in the events module.

process.stdout is a stream$Writable or a tty$WriteStream, so almost the entire contents of the stream and tty modules have to be global too.

our current thinking is to add a global modifier, like this:

declare module 'process' {
  declare type Process = ...

  declare global var process : Process
}

mroch avatar Jul 16 '21 19:07 mroch

@mroch I think this request is a bit different, where types.js is not a libdef but they want to use the definitions in that file from a libdef.

@bluepnume I don't think this ever worked, but instead Flow would silently use any in your program and now we complain loudly. Library definitions can't reference other modules, since we would not be able to incrementally update the builtins when that module changes.

If you need to declare a global like this, then your best bet is to define the types declarations.js as well.

samwgoldman avatar Jul 16 '21 22:07 samwgoldman

I'm merely trying to import one libdef from another. In particular, I've been trying to write Flow types for @babel/types, @babel/core, etc.

Almost all the modules depend on the types from @babel/types. But @babel/types is a large file and it's not feasible to copy all the types in each module.

I tried solving this by adding top-level imports. The funny thing is that it actually works, but it still gives me type errors.

nmn avatar Jun 29 '22 05:06 nmn

+1 it's weird that we can't re-use types in declarations

dominictobias avatar Aug 24 '23 17:08 dominictobias