TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Can't augment function overload is function is exported via `export {}`

Open eps1lon opened this issue 1 year ago • 3 comments

🔎 Search Terms

TS2383, function overload, module augmentation

🕗 Version & Regression Information

  • This is a crash
  • Prior to 3.2.4 you'd get "TS2484: Export declaration conflicts with exported declaration of 'get'."

⏯ Playground Link

https://github.com/eps1lon/tsc-augment-overload

💻 Code

// library.d.ts
declare function get(): string;
declare function set(value: string): void;

export { get, set };

// app.d.ts
import "library";

declare module "library" {
  function get(): string | null;
}

// index.ts
import { get, set } from "library";

// module augmentation did work
const value = get();
//    ^? string | null
// @ts-expect-error Argument of type 'string | null' is not assignable to parameter of type 'string'.
set(value);

🙁 Actual behavior

$ yarn tsc --skipLibCheck false
app.d.ts:4:12 - error TS2383: Overload signatures must all be exported or non-exported.

4   function get(): string | null;
             ~~~


Found 1 error in app.d.ts:4

🙂 Expected behavior

No error since the module augmentation seems to have worked.

Additional information about the issue

As a workaround, we can switch to

-function get(): string
+export function get(): string
-export {get}

though this seems like TypeScript is enforcing a certain code style. Some teams prefer writing a single export {} statement.

eps1lon avatar Jun 03 '24 17:06 eps1lon

I’m guessing the argument is that this should work because the original library wrote export { get } instead of exporting functions individually. But that’s an implementation detail - it shouldn’t be able to affect how the augmenting file is allowed to be written.

fatcerberus avatar Jun 03 '24 18:06 fatcerberus

I’m guessing the argument is that this should work because the original library wrote export { get } instead of exporting functions individually. But that’s an implementation detail - it shouldn’t be able to affect how the augmenting file is allowed to be written.

I'd be fine with the constraint if we could actually write export {} in module augmentations but we can't. We get these two errors instead:

  1. Exports and export assignments are not permitted in module augmentations.(2666)
  2. Export declaration conflicts with exported declaration of 'X'.(2484)
import * as React from 'react'

declare module 'react' {
  function useId(): string | null

  export {useId}
}

Playground Link

eps1lon avatar Jun 04 '24 11:06 eps1lon

@eps1lon I am also facing this issue (Exports and export assignments are not permitted in module augmentations.) when wanting to re-export types from one module into the global.

// utils.d.ts
declare module "caido:utils" {
  export class Body {
    constructor(data: string | Array<number> | Uint8Array);
  }
}

// typing.d.ts
import type {
  Body as _Body,
} from "caido:utils";

declare global {
  export { _Body as Body };
}

Sytten avatar Jun 28 '24 21:06 Sytten