Open reverofevil opened 3 years ago
This is a pretty heavy lift from the architecture side since, during the typechecking phase, we generally don't go do new expensive I/O. We could potentially allow it for modules that are already in scope (probably pretty common) but if you already know the completely list of modules you might want to look up this way, it's pretty straightforward to write a helper type somewhere with that list instead of using typeof import
at the use site
@RyanCavanaugh Doesn't typeof import()
already do the same thing during typechecking phase?
The criteria "module has to be in scope" doesn't apply to babel
, webpack
and eslint
, because neither of them imports modules from callee side at all.
If you let me add my subjective 2 cents, this feature is required to correctly type check at least 5 core frontend libraries, so it seems this is quite an important heavy lift to do.
My use case is that my library has support for mocking dynamic imports. Essentially the api looks like this:
const {mockedImport} = await importer.import("path/to/import.js");
The api closely mimics dynamic import()
syntax. So it would be nice if the returned type from this function would return the same type as you would get when actually dynamically importing it. If this were supported the signature could look like:
async importWrapper<T extends string>(url: T) : Promise<typeof import(T)>
Right now I'm resorting to using the module itself as a generic parameter. But using it like this is kind of ugly:
const {mockedImport} = await importer.import<typeof import("path/to/import.js")>("path/to/import.js")
Having the same issue with vitest
, this could be a nice feature!
import { vi } from "vitest";
export function importActual<T extends Parameters<typeof vi.importActual>>([path, ...args]: T): ReturnType<typeof import(`${T[0]}`)> {
return vi.importActual(path, ...args);
}
@RyanCavanaugh would it help if there was a new module
primitive, such that any generic of type module is part of a first pass (before general type checking) which does all I/O. Then during type checking phase is performing a lookup on a table of all modules that were loaded during I/O phase.
It seems like something like this might be necessary if module expressions land. I imagine module expressions would be type module & Module
(Module
being the type for the class instance).
Usage could look like this:
function lazyImport <M extends module>(pathOrModule: M): () => typeof import(M) {
return () => import(pathOrModule);
}
To add one more use case, we use jest in out React application. And jest have ability to mock modules. To keep it typesafe we use the following pattern:
jest.mock(
'path/to/module',
(): typeof import('path/to/module') => ({ }),
);
If we could use generic import types it would make it less verbose and would remove duplication of path.
same issue with jest and mocked functions. if you go the road and import the globals (instead of using ambient types), jest.SpiedFunction<T>
expects a generic. if you combine this with isolateModules
where you always want dynamic imports, you get types like this:
const myFnSpy = jest.SpiedFunction<typeof import("my-imported-module")["myImportedFunction"]>;
you can imagine this getting a bit verbose if you need a lot of spies in a test
When can we expect this to land?
What's the current status of this feature? Is there an expected support time?
Suggestion
π Search Terms
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Add ability to
typeof import()
a string literal typeπ Motivating Example
π» Use Cases
babel
,eslint
andwebpack
use package names in their API, dynamicallyrequire
them and proxy data into their interface. Generally, API that looks likecould greatly improve on typing with this.
Also it's often the case with dynamic imports that resulting
Promise
gets passed through several other methods (likeReact.lazy
orloadable
from@loadable/component
). Currently the only way to get good types there is to have these duplicated at everyimport()
site. It would be possible to assign some types to wrapper function in this case too.