typescript - Hur kan jag återexportera en pakets fullständiga uppsättning av typer?


Paketet foo har många användbara TypeScript-gränssnitt som jag vill exponera transitivt genom paketet bar till konsumenter (representerade som paketet baz), men jag kan inte hitta ett elegant sätt att återexportera hela uppsättningen typer (namnrymd?) för downstream-användning. foo är ett ofta förändrat beroende som jag inte underhåller strikt. Det är viktigt att dess gränssnitt automatiskt återspeglas genom bar, eftersom bar är den enda leverantören av foo till baz.

Överväg följande paketberoendekedja:

foo -> bar -> baz

Överväg nu några grundläggande implementeringar:

// pkg foo
export interface Fooz { x: number }
// pkg bar
import * as foo from 'foo';

// Objective: get all interfaces/types re-exported through this package
export type FooMod = import('foo');
// ^ This would be ideal, but not supported
// Module 'foo' does not refer to a type, but is used as a type here. Did you mean 'typeof import('foo')'?ts(1340)
// pkg baz
import * as bar from 'bar';

// This is my end customer's package. How can they get to interfaces from `foo`, hosted by `bar`? 
// e.g. observe the return type:
const doStuffWithBar = (): bar.FooMod.Fooz => {
  // 
}

Saker jag har provat hittills:

  1. export FooMod=typeof foo;. typeof foo skapar en ny typ och är förlorande. Det kan ta med typer från alla enheter som fysiskt finns i modulen, men typer/gränssnitt från foo-modulen tas bort. Detta är inte tillräckligt.
  2. export FooMod=import('foo'). Detta ger ett TS-fel, nämnt i kommentarerna inline.

Utan en lösning måste jag tvinga mina kunder att faktiskt installera foo-modulen för att komma åt dess top-nivåtyper. Jag skulle också kunna inlinea exports i bar för alla typer i foo, men det är inte hållbart, och med tanke på storleken och förändringstakten hos foo är det värsta möjliga resultat.

Är en sådan lösning möjlig?

Svar #1

Använd export * (as X)? from 'package' i Bar. Om du vill importera typerna direkt i Baz, hoppa över as <X>, annars kan du importera namnområdet i Baz som i exemplet nedan:

Foo

// index.ts
export interface Test {
  a: string
}

Namnutrymme import i Baz

Bar

// index.ts
export type * as Foo from 'foo';

Baz

import { Foo } from 'bar';

let a: Foo.Test;

Direkta typimporter i Baz

Bar

// index.ts
export type * from 'foo';

Baz

import { Test } from 'bar';

Redigera: Som noterats av OP:s kommentar, även med export types kommer de icke-typ-exporterna i Foo också att visas vid import i Baz. Men de kan inte användas i Baz, eftersom TypeScript kommer att ge felet: <variable> kan inte användas som ett värde eftersom det exporterades med 'export type'. och det ser inte ens ut som om de faktiskt är exporterade från Bar, bara i namn i deklarationsfilen.