Exported variable X has or is using name Y from external module Z but cannot be named
Asked Answered
N

3

8

I get the following error in this case using TS 3.9 with { compilerOptions: {declaration: true }} in my tsconfig.json:

// a.ts
export const key = 1234
export const obj = {
    [key]: 1
};
export default obj;

// b.ts
import A from "./a";
import { key} from "./a"

// Exported variable 'theExport' has or is using name 'key' from external module "c:/tsexample/src/a" but cannot be named.ts(4023)
const theExport  = {
  A: A,
  B: 2,
  C: 3,
};
export default theExport
// Exported variable 'theExport' has or is using name 'key' from external module "c:/tsexample/src/a" but cannot be named.ts(4023)

In a comment on a related issue the PM of TS at the time suggested two workarounds:

  1. explicitly import the type
  2. explicitly declare the type of the export (where the error occurs)

(1) does not work in this case. I tried exporting everything from 'a' and importing everything in 'b' and there was no difference to the error message.

The only thing that worked was this very verbose and hard to maintain explicit type annotation:

// updated b.ts
import A from "./a";

const theExport: {
    // https://github.com/microsoft/TypeScript/issues/9944
  [index: string]: typeof A | number;
} = {
  A: A,
  B: 2,
  C: 3,
};
export default theExport;

My question is:

  • what is a workaround I can use that doesn't involve repeating the shape of the object?
  • why does importing the type not fix the problem?

This question is similar but distinct from:

Nadaba answered 23/6, 2020 at 15:27 Comment(2)
were you able to come up with anything more elegant in the end?Solenoid
I repeated the shape for small things and did something like https://mcmap.net/q/1349726/-exported-variable-x-has-or-is-using-name-y-from-external-module-z-but-cannot-be-named for long things iirc. I switched roles and unfortunately don't know if my colleagues found something better or figured out why this corner of the language is suddenly pedantic.Nadaba
S
5

It's not that pretty, but this is a minimally invasive change that seems to work in a sandbox:

const theExport = {
  A: A as {[K in keyof typeof A]: typeof A[K]},
  B: 2,
  C: 3
};
Shanel answered 28/10, 2020 at 5:29 Comment(1)
I like it! no maintenance requiredWon
W
1

based on this comment, looks like one solution could be:

// a.ts
export const key = 1234
export const obj = {
    [key]: 1
};
export default obj;

// b.ts
import A from "./a";

interface ITheExport {
  A: typeof A;
  B: number;
  C: number;
}

const theExport: ITheExport = { // strong typing the object instead of using inference
  A: A,
  B: 2,
  C: 3,
};
export default theExport

See sandbox

Won answered 28/10, 2020 at 4:30 Comment(0)
B
0

Explicitly set obj type

// a.ts
export const key = 1234
export const obj = {
  [key as number]: 1
}
export default obj

// b.ts
import A from './a'

const theExport = {
  A: A,
  B: 2,
  C: 3
}
export default theExport
Blankenship answered 2/11, 2020 at 11:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.