Typescript: Spurious "Identifier 'angular' must be imported from a module" error

Created on 31 Aug 2016  路  17Comments  路  Source: microsoft/TypeScript

TypeScript Version:

2.0.2

Code

https://github.com/jonrimmer/typescript-bug

npm install
./node_modules/.bin/tsc bug.ts

Expected behavior:

It should compile without problems.

Actual behavior:

It gives the following error:

node_modules/angular-ui-router/commonjs/ng1/services.d.ts(2,27): error TS2686: Identifier 'angular' must be imported from a module

This is despite the fact that the @type/angular definitions includes a global angular var declaration.

Fixed Suggestion

Most helpful comment

I have to be honest, while I basically understand the reasoning, the choice of making this work globally only if there are no imports or exports in the file seems completely arbitrary and comes across as a bad choice for both usability and backwards compatibility. At the very least this should have been configurable or provide an easy way to work around it.

I am now spending a great deal of what feels like unnecessary time on this while trying to move a fairly large project towards Angular 2 and Typescript 2 and this is creating unnecessary friction. If every update to the Typescript project is going to just add a new bar to jump over like this I'm really going to need to reconsider using it.

So far I've found this to be a common pattern with using Typescript. Many inexplicable behaviours and decisions each of which is hard to track down or find documentation around.

All 17 comments

I have the same problems (trying to switch from typings to @types in my project)

To be more clear:
I just change my typings setup (angular, jquery, lodash, angular-ui-router) with same @types and

    "typeRoots": ["node_modules/@types"],
    "types": ["lodash", "jquery", "angular", "angular-ui-router"]

in my tsconfig.json and starting to get dozens of "Identifier 'angular' must be imported from a module" errors during my webpack build.

Typescript 2.0 and 2.0.2, webpack 2.1-beta.21+awesome-typesript-loader.

this is an issue in angular-ui-router declaration file. The compiler tries to ensure that a UMD module is used consistently, either as a module or as a global.

File: node_modulesangular-ui-router\commonjs\ng1\services.d.ts

should be:

import * as angular from "angular";
import IInjectorService = angular.auto.IInjectorService;

I don't think this is an angular-ui-router issue. I have the same problem without that installed coming from any local file that references angular.

Adding import * as angular from "angular" to every file is obviously one way to fix this, but this was not a problem before when I was using typings instead of @types. If this is just how the new type definition resolution works now then that is pretty disappointing.

Worth noting that only angular seems to have this problem, jQuery, Lodash and others are working fine.

the rational here, is some libraries are available as either module or a global. if you are using them as a module, all references should be done this way. the warning aims to notify you about this discrepancy. this is a new feature added in TS 2.0 see https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#support-for-umd-module-definitions for more details.

I have to be honest, while I basically understand the reasoning, the choice of making this work globally only if there are no imports or exports in the file seems completely arbitrary and comes across as a bad choice for both usability and backwards compatibility. At the very least this should have been configurable or provide an easy way to work around it.

I am now spending a great deal of what feels like unnecessary time on this while trying to move a fairly large project towards Angular 2 and Typescript 2 and this is creating unnecessary friction. If every update to the Typescript project is going to just add a new bar to jump over like this I'm really going to need to reconsider using it.

So far I've found this to be a common pattern with using Typescript. Many inexplicable behaviours and decisions each of which is hard to track down or find documentation around.

Considering removing the restriction on UMD globals to only apply to values. There's not much point to enforce uniformity in type/namespace usage.

Thanks @RyanCavanaugh it is probably also worth noting that calling import * as angular from 'angular' in each file does not work properly with Webpack as it will try to load angular multiple times.

The only solution is to add declare var angular at the top of each problematic file, which is far less than ideal.

... does not work properly with Webpack as it will try to load angular multiple times.

How does anyone use Webpack with modules, ever, if this is its behavior? Can you show a small example of how repeated imports would lead to a problem?

It's a fair question, there may be issues currently with Webpack 2 changes working with the TS loaders actually. I've found both ts-loader and awesome-typescript-loader can behave inconsistently with respect to just running tsc

Also the behaviour may have been specific to running on the webpack-dev-server. I didn't spend a ton of time testing it.

I'll see if I an produce a small example when I have a chance.

@mhegazy @RyanCavanaugh @rkirov We have ~3k source files across multiple projects that rely on the old behavior. Do you have any advice on how to update to the new typings? I'm happy to update to the new module-like behavior but I was hoping to make some sort of temporary shim (that makes the new "angular" module also available as a global) so I could migrate a few files a time. It seems this error is accidentally designed to prevent us from that(?).

@chrisnicola Webpack has a loader called CommonChunksPlugin that checks to see what modules have already been loaded to be sure not to have 2 in the bundle.

Yet another day wasted trying to make TSC happy. Yes yes, we all should modules, but not every library out there is compliant or nice. So this nonsense has got to stop.

@mhegazy Wow, that is a DUMB idea. I can't believe they are doing that, especially when trying to support legacy code bases.

By the way, the title problem was solved by me in that way:

// _shim.d.ts
import * as __angular from "angular";

declare global {
    const angular: typeof __angular;
}

@Gugic Apparently my globals file can't declare a globals namespace because its not ambient though it ends in .d.ts due to something else silently triggering it not being ambient or something

Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.at line 64 col 9

There are so many pitfalls in ts modules

My globals.d.ts now consists entirely of

declare global {
}

and I still get that error

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jbondc picture jbondc  路  3Comments

remojansen picture remojansen  路  3Comments

manekinekko picture manekinekko  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments

kyasbal-1994 picture kyasbal-1994  路  3Comments