Skip to content

[ts2.6 regression] cannot name symbols referring to types using declare global #20749

Closed

Description

TypeScript Version: 2.6.2 & 2.7.0-dev.20171216

Code

// module.d.ts (from the AngularJS typings)
declare var angular: angular.IAngularStatic;

export = angular;
export as namespace angular;

declare namespace angular {
  export interface Module {}
  interface IAngularStatic {
    module(): Module;
  }
}

// globalize.d.ts
import * as alias from './module';

declare global {
  const angular: typeof alias;
}

// user.ts
export const foo = angular.module();

Compile with tsc --declaration

Expected behavior:

In TS2.5, this compiles fine, and produces a .d.ts with export const foo: angular.Module;, i.e. using the global alias for the module-scoped type.

Actual behavior:

In TS2.6+, this complains the symbol cannot be named:

user.ts(2,14): error TS4023: Exported variable 'foo' has or is using name 'angular.Module' from external module ".../module" but cannot be named.

Activity

  1. weswigham commented on Dec 20, 2017

    @weswigham
    Member

    Two things at play here, and fixing this needs a small patch to the compiler and maybe an update to angular's definitions.

    That this worked at all in the first place was due to a bug. #18049 fixed the bug enabling this. UMD aliases should not have been considered visible with modules for declaration emit, since they are not looked up when checked later (and thus will cause downsteam errors in consumers if the types get emitted relying on them). Hence the current error. Now, the global patch is supposed to work around that, I imagine, by always exposing the global - except there are two issues. One is that we don't consider a symbol which is both a UMD symbol and not-a-UMD-symbol as visible in a module since the aforementioned bug fix - I have a correction for that now up at #20837. That's the case here because export as namespace angular is creating a UMD export symbol, and const angular in declare global is creating another declaration for that symbol (which should probably take priority over the information infered by the UMD one).

    The other is an issue with your global patch:

    declare global {
      const angular: typeof alias;
    }

    should only be enough to make a call to angular.module typecheck (which is why you were able to get away with it sometimes), but shouldn't actually reexpose any of the types the alias namespace has in the global namespace. So it's return type, Module, should not be nameable even once I change it so that symbols which are both umd exports and not umd exports are considered usable. The types from the UMD export part of the symbol still shouldn't be visible, so you should still need to reexport all of your types in your global patch as well, ie:

    declare global {
      namespace angular {
        export type Module = alias.Module;
      }
      const angular: typeof alias;
    }
  2. weswigham commented on Dec 20, 2017

    @weswigham
    Member

    I adjusted my wording in my prior post to say "should" in many places in the second half because the simple fix in #20837 is insufficient to actually break the negative case correctly; so even if you don't reexport the types in your globalize.d.ts, it'll still emit types without error (and typecheck the definition file without error); however that's liable to cause errors in downstream consumers (because UMD globals aren't visible within modules, once someone consumes something using user.ts's declaration output and tries to print it's type, they'll get visibility errors).

    In short, #20837 gets the old behavior back for your case, but it's usage is able to cause issues like those mentioned in #16155 (at least if you do not have a complete declare global patch), so you probably shouldn't rely on the types being erroneously made available through the UMD namespace since it causes issues for consumers and we're likely to fix it.

  3. weswigham commented on Dec 17, 2018

    @weswigham
    Member

    This should have been fixed (in 3.2 even) by #28909.

  4. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptDomain: Declaration EmitThe issue relates to the emission of d.ts files

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions