piotrwitek/react-redux-typescript-guide

How to re-export interface in an ambient module ?

chawax opened this issue ยท 6 comments

Hi,

In my app I have code for API Client generated from Swagger Code Gen. The code includes models such as this :

export interface Echelon {
    id?: number;
    code?: string;
    libelle?: string;
}

When I need to import this type, I have to use a relative import :

import { Echelon } from '../../../services/Api/swagger';

It works but I am not a fan of that. I'd like to have a import from an ambient module, something like that (i.e. the same way it works with ApplicationState in playground project) :

import { Echelon } from 'Models';

But I can't find the way do to this.

import { Echelon } from '../services/Api/swagger/api';
declare module 'Models' {
   export interface Echelon
}

Any idea ?

Should work, make sure this file is d.ts and is located in the folder included in tsconfig

It is in a .d.ts file in the same folder than my index.d.ts file that is used to declare module Types.

Actually it looks like the problem is with exporting interfaces in an ambient module.

I tried this :

declare module 'Models' {
  export { Echelon } from '../services/Api/swagger/api';
}

But I have this error : "Import or export declaration in an ambient module declaration cannot reference module through relative module name. ts(2439)"

I also tried this but can't find the right way to write it :

import { Echelon } from '../services/Api/swagger/api';

declare module 'Models' {
  // ???
}

If you're re-exporting existing interface, I would suggest to create a new alias for type or in case of interface create a new that extend exsiting one. Should solve the export issue.
e.g.

declare module 'Models' {
  // imports go inside for augmentation
  import { Echelon as BaseEchelon } from '../services/Api/swagger/api';

  export interface Echelon extends BaseEchelon { }
}

I won't go into the details because they are basics that you can learn from typescript documentation modules section.

Note to myself:
Extend module imports section with a mention for augmentation to include imports inside

Thanks a lot again @piotrwitek !

chpio commented

Im getting the same error as @chawax with:

declare module "core-js-pure/features/iterator" {
    import { ExtendedIterator as BaseExtendedIterator } from "./utils/iter";
    interface ExtendedIterator<T> extends BaseExtendedIterator<T> { }
    export function from<T>(it: Iterable<T>): ExtendedIterator<T>;
}

Import or export declaration in an ambient module declaration cannot reference module through relative module name. ts(2439)

on the import.


Moving the import out:

import { ExtendedIterator } from "./utils/iter";
declare module "core-js-pure/features/iterator" {
    export function from<T>(it: Iterable<T>): ExtendedIterator<T>;
}

results in a rather unintelligible error message:

Invalid module name in augmentation. Module 'core-js-pure/features/iterator' resolves to an untyped module at '[...]/node_modules/core-js-pure/features/iterator/index.js', which cannot be augmented. ts(2665)

I guess you just can not define a module if there are relative imports in the same file.


So at least i made it compile with:

declare module "core-js-pure/features/iterator";

which results in core-js-pure/features/iterator being any.

The error is due to the limitation that you can't do a relative imports inside an ambient declaration directly. You can use the import() syntax
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#import-types