mollwe mollwe - 1 year ago 71
TypeScript Question

Automatic ordering of exports in index.ts makes app crash

Every time I generate something in my shared folder the index.ts file is rebuilt and exports are put in alphabetical order. This seems to break dependencies for me. Changing order manually so that dependencies is exported before classes with the dependencies makes it work again.

If we have


import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

import { AuthService, User } from './';

export class AuthGuard implements CanActivate {

constructor(private accountService: AuthService, private router: Router) { }

canActivate(next: ActivatedRouteSnapshot): Observable<boolean> {
let result = this.accountService.currentUser.first().map(user => user != null);

let route: any[] = ['/login'];

if (next.url.length) {
route.push({ redirectUrl: next.url });

result.subscribe(isLoggedIn => {
if (!isLoggedIn) {

return result;


import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { User } from './';

const LOCAL_STORAGE_KEY = 'currentUser';

export class AuthService {
private currentUserSubject: BehaviorSubject<User>;

constructor() {
this.currentUserSubject = new BehaviorSubject<User>(this.getUserFromLocalStorage())
this.currentUserSubject.subscribe(user => this.setUserToLocalStorage(user));

logIn(userName: string, password: string) : Observable<User> {{
id: userName,
userName: userName,
email: userName

return this.currentUser.first();

logOut() {;

get currentUser(): Observable<User> {
return this.currentUserSubject.asObservable();

private getUserFromLocalStorage(): User {
let userString = localStorage.getItem(LOCAL_STORAGE_KEY);

if (!userString) {
return null;

return JSON.parse(userString);

private setUserToLocalStorage(user: User) {
if (user) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(user));
else {


This doesn't work:

export * from './auth.guard';
export * from './auth.service';

Unhandled Promise rejection: Error: Cannot resolve all parameters for 'AuthGuard'(undefined, Router). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthGuard' is decorated with Injectable.

This works:

export * from './auth.service';
export * from './auth.guard';

From what I noticed this doesn't apply to all. For example can my user model be exported after auth service and it works fine.

I wish I didn't have to change this manually every time. Is there a workaround available? Could I structure the files in a different way?

Dependencies from

"@angular/common": "^2.0.0-rc.2",
"@angular/compiler": "^2.0.0-rc.2",
"@angular/core": "^2.0.0-rc.2",
"@angular/forms": "^0.1.0",
"@angular/http": "^2.0.0-rc.2",
"@angular/platform-browser": "^2.0.0-rc.2",
"@angular/platform-browser-dynamic": "^2.0.0-rc.2",
"@angular/router": "^3.0.0-alpha.7",
"bootstrap": "^3.3.6",
"es6-shim": "0.35.1",
"moment": "^2.13.0",
"ng2-bootstrap": "^1.0.17",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"slideout": "^0.1.12",
"systemjs": "0.19.26",
"zone.js": "0.6.12"


"angular-cli": "1.0.0-beta.6"

Answer Source

This is an issue with ordering of exports in barrels. It has been reported in the angular repo here:

There are three workarounds:

Change the ordering of exports in your barrels

Change the ordering so that module dependencies are listed before their dependants.

In this example, AuthGuard depends on AuthService. AuthService is a dependency of AuthGuard. Therefore, export AuthService before AuthGuard.

export * from './auth.service';
export * from './auth.guard';

Don't use barrels at all.

This is not recommended since it means more imports are required.

In this example, you would import AuthService from its file rather than a barrel.

import { AuthService } from './auth.service';
import { User } from './';

Use the systemJS module format rather than commonJS

Change the typescript compiler options to compile to the SystemJS format rather than commonJS. This is done by changing tsconfig.json's compilerOptions.module from commonjs to system.

Note that when you change that configuration, you'll need to update the moduleId properties of all your component decorators from to __moduleName and declare it in typings.d.ts as follows:

declare var __moduleName: string;

This module format is not the default in the Angular-CLI tool (official build tool created by the Angular team) and so may not be recommended or supported.

Note: I'm personally not satisfied with any of the workarounds.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download