Kan TypeScript hente typen til en importert modul via dens sti?


Jeg prøver å skrive en wrapper rundt jest.isolateModules kalt test.isolated(). Funksjonen tar inn et array av strenger som representerer modulene testen ønsker importert, etterfulgt av de vanlige argumentene (name, fn, timeout), og injiserer deretter et objekt med hver av de importerte modulene etter navn som det første parameteret til fn.

Innholdet i test.isolated er lett nok å skrive ved bruk av proxyer. Jeg vil vite hvordan jeg kan gi det første argumentet sterk type.

På en eller annen måte kan VS Codes TypeScript-motor bestemme typen til eksportene fra en importert modul. Er det mulig å utlede den typen (returtypen til require()) basert på banen til modulen?

Mitt første forsøk var:

type ModuleType<M extends string> = 
  ((m: M) => ReturnType<NodeRequire>) extends ((m: M) => infer U) ? U : never;

type T = ModuleType<'fs'>;

Merkelig nok er T typeof Electron uansett hva jeg setter inn for M. Det ser ut til at ReturnType<NodeRequire> er typeof Electron selv i prosjektet mitt.

Andre forsøk:

type ModuleType<M extends string> = 
  ((m: M) => NodeRequire['main']['exports']) extends ((m: M) => infer U) ? U : never;

type T = ModuleType<'fs'>; // => any

Ideer? Eller er dette rett og slett ikke mulig?

Rediger: Jeg har oppdaget at returtypen til require() alltid er any. Bare import-syntaksen utleder en type.

Svar #1

Ser ut til å være en ofte etterspurt funksjon som er umulig akkurat nå (og jeg skulle gjerne hatt den også). For eksempel.

  • https://github.com/microsoft/TypeScript/issues/41550
  • https://github.com/microsoft/TypeScript/issues/56242
  • https://github.com/microsoft/TypeScript/issues/31090
  • https://github.com/microsoft/TypeScript/issues/44636

Svar #2

Støtte akkurat på dette samme problemet (år senere) og klarte å få dette til å fungere:

function doSomethingWithModule(m: typeof import('*.js')) {
  // in here, m is a module type
}

Så, du kan sannsynligvis gjøre noe som:

type SomeKindOfModule =
  typeof import('*.js') |
  typeof import('*.scss') |
  typeof import('*.cjs') |
  typeof import('*.mjs');