Typescript: Typescript gets confused with a variable and an imported interface with the same name

Created on 3 Mar 2016  ·  16Comments  ·  Source: microsoft/TypeScript

TypeScript Version:
1.8.0-1.8.7

Code

import {Key} from 'types'; // Key is an interface
const Key = { test() {} };
Key.test();
export default Key;

Expected behavior:

Key.test();
exports.default = Key;

Actual behavior:

types_1.Key.test();
exports.default = types_1.Key;
Bug

Most helpful comment

I don't see why this should be fine...

interface Key {}
const Key = {};
export default Key;

...and this should not:

interface.ts

export interface Key {}

key.ts

import {Key} from './interface';
const Key = {};
export default Key;

All 16 comments

We should be issuing a Duplicate Identifier error on Key since we otherwise couldn't emit this correctly in transpile scenarios

Key is an interface though. It doesn't have any value. It shouldn't be a duplicate identifier.

The problem is that when a file gets compiled through ts.transpile, we don't do any module lookup, symbol resolution, etc, so we have no way of knowing that that is the case.

I don't see why this should be fine...

interface Key {}
const Key = {};
export default Key;

...and this should not:

interface.ts

export interface Key {}

key.ts

import {Key} from './interface';
const Key = {};
export default Key;

I see your point...

how about this:

when #transpile sees two duplicate identifiers, it checks if the local definition has a value. if it does (i.e. the local definition is not an interface/type) #transpile uses it. if it doesn't have a value, #transpile uses the imported one.

when #transpile sees two duplicate identifiers, it checks if the local definition has a value.

The meanings of a local declaration could be still sourced in another file. Consider

a1.d.ts

namespace X {
  export interface Y { }
}

a2.d.ts

namespace X {
  export var Y;
}

foo.ts

// might be referencing a1 *or* a2, we can't tell
import Key = X.Y;

in that case both namespaces have the same name X. we don't have a2_1.X. as there's no import ... from.

And you can't have duplicate namespaces I believe.

/// <reference path="a2" />
import {X} from 'a1';

shouldn't work.

IKey, would be nice if there was community acceptable of the I paradigm

Is this thread still relevant @RyanCavanaugh? I don't want to create new issue even if mine isn't exactly the same as other Duplicate Identifier posts but I can if a moderator or contributor says that I should because this thread hasn't been used in almost two years. But here is my issue with the Duplicate Identifiers.

//*******
// Declare any non typeScript functions here to avoid compile errors
//*******
declare var HeyImGlobal: any;
//*******

export class TsModule extends HTMLElement {
    HeyImGlobal(param1, param2, param3);
}

For my example I have a project that has access to many global variables that are defined elsewhere, in this example it's HeyImGlobal. When creating a new TS file I cannot use that global variable unless I declare it at the top like declare var HeyImGlobal: any; so the code in the same file knows about the variable or else you'll get the "Cannot Find Name" error. Visual Studio will build and compile TypeScript just fine with the code above but VS Code will _not_ even though _both_ will show the same error that the declaration declare var HeyImGlobal: any has a "Duplicate Identifier". I can also use the global variable when it builds and compiles so the code works. But I am blocked from using VS Code because the compiler is finding the variable in another file when declaring it.. This stops me from using VS Code to compile TypeScript files which sucks. I do have the "files": [] property filled out in tsconfig.json with the only three TypeScript files that I have and I thought that would stop the detection in other files but I'm probably misunderstanding that part.

Yes a flag would be great or at least something just to get around what's preventing me from using and compiling with VS Code.

@DanJ210 It sounds like VS Code has found some additional files that the compiler does not when invoked from the command line. But I don't think you have found a bug necessarily, and definitely not the bug from this issue.

I would ask at Stack Overflow or the Typescript gitter channel for help debugging which files VS Code is including in the compilation.

@sandersn I've seen the file. Visual Studio will show where the variable is getting picked up at. If I know the file then what can I do at that point?

Record your file system layout and tsconfig. Then ask a question on SO or TS' gitter, giving that information. You might also try --traceResolution from the command line to see why that file doesn't get picked up.

Update for the new decade:

  • Emit bug as filed no longer repros
  • Should be a duplicate identifier / declaration merge error only in --isolatedModules, but triggers no error today
  • Said error can be resolved by using a type-only import (#35200)

Going to put this on my plate for 3.9 since I stumbled upon it and it overlaps stuff I’ve worked on recently.

Should be a duplicate identifier / declaration merge error only in --isolatedModules, but triggers no error today

I think I was wrong about this—if the emit always does the right thing, even in transpilation, and the code makes sense in whole-program compilation, I don’t see why there should be an error. Feel free to comment/reopen if I’m wrong.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Antony-Jones picture Antony-Jones  ·  3Comments

dlaberge picture dlaberge  ·  3Comments

bgrieder picture bgrieder  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

MartynasZilinskas picture MartynasZilinskas  ·  3Comments