Angular 1.x with TypeScript 2.x, @types, and SystemJS - Using global typings

Kerry Ritter picture Kerry Ritter · Nov 17, 2016 · Viewed 10.3k times · Source

I am trying to use Angular 1.x with the new TS2 and @types registry but running into problems. It looks like @types does not use what the typings registry refered to as "global" typings. I am running into the following error:

error TS2686: 'angular' refers to a UMD global, but the current file is a module. Consider adding an import instead.

The angular code is as following:

import "angular";
import "angular-route";

const app = angular.module("charter-app", ["ui.bootstrap", "ui.router", "templates", "charter-app.controllers"]);

tsconfig.json:

{
    "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "mapRoot": "./",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5",
    "inlineSources": true,
    "removeComments": false,
    "noImplicitAny": false,
    "typeRoots": [ "node_modules/@types/" ],
    "types": [ "angular", "angular-ui-bootstrap", "angular-ui-router" ],
    "outFile": "app.js"
    }
 }

Trying to use the following

"devDependencies": {
    "@types/angular": "^1.5.20",
    "@types/angular-ui-bootstrap": "^0.13.35",
    "@types/angular-ui-router": "^1.1.34",

I'm using gulp-typescript to do the compilation. What am I missing? Can I not use the @types libraries for this purpose?

Answer

PSL picture PSL · Feb 4, 2017

I can think of 2 approaches here.

1) Mark angular as global. (Much easier migration option)

Create a d.ts file say overrides.d.ts and do:

declare global {
  const angular: ng.IAngularStatic;
}
export {};

or

import * as _angular_ from 'angular';

declare global {
  const angular: typeof _angular_;
}

and that's it, no need to import or manage script loading separately for this.

2) Import it in every impacted file. (May be more tedious migration option on a large existing project)

If you can go ahead update all the impacted files (Usually a bit hard to take this approach in a much big project which already has lots of error related to this) where ever you refer to angular, import it:

import * as angular from "angular";

If you are taking this approach, typescript will transpile with angular as a dependency for the file and your module loader (eg: SystemJS) needs to handle the import. This may be done either by having systemJS manage the imports via maps/paths or if the script is loaded by script tags then you can create a fake module for angular by using SystemJS.registerDynamic or SystemJS.set apis.