Order of Import statements in Angular 2

The Angular Style Guide says of Import line spacing:

  • Consider leaving one empty line between third party imports and application imports.
  • Consider listing import lines alphabetized by the module.
  • Consider listing destructured imported symbols alphabetically.
  • Why? The empty line separates your stuff from their stuff.
  • Why? Alphabetizing makes it easier to read and locate symbols.

Looking at many Angular projects including Angular itself the convention is to import Angular (@angular) modules first, then third-party modules (e.g. AngularFire2) and then our own modules (Services, Components, etc.) e.g. ./some-service.ts.

Again it looks like it is the convention to import Services, then Models and then Components.

But what about Interfaces and Pipes, etc.? And what is the convention for importing 'nameless' or wildcard modules, e.g. the Firebase SDK or RxJs operators?

For example:

Example Service that Imports an RxJs Operator

import { Injectable } from '@angular/core';

import { AngularFireAuth } from 'angularfire2/auth';
import {
  AngularFireDatabase,
  FirebaseListObservable
} from 'angularfire2/database';
import * as firebase from 'firebase/app';
import 'rxjs/add/operator/take';
...

Or

import { Injectable } from '@angular/core';

import {
  AngularFireDatabase,
  FirebaseListObservable
} from 'angularfire2/database';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';

import { AuthService } from './auth.service';
// `GridMetadata` is an Interface
import { GridMetadata } from './grid-metadata';
...
angularconvention

Answers

answered 11 months ago Jonathon Oates #1

Actually, looking at the Angular codebase and with a better understanding of the guidelines, there is an answer.

"Consider leaving one empty line between third party imports and application imports."

This just needs an example to explain it:

// Core imports
import { TestBed, async, inject } from '@angular/core/testing';

// Third party imports
import { AngularFireAuth } from 'angularfire2/auth';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/of';

// Application imports
import { AuthService } from './auth.service';
import { environment } from '../environments/environment';

"Consider listing import lines alphabetized by the module."

Think of the 'modules' as the bit after "from". The modules contain the symbols to be imported.

import { Injectable } from '@angular/core';

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';

It doesn't matter what the symbols are; it is only important that import lines are alphabetised by the module. e.g.

  1. angularfire2/auth
  2. firebase/app
  3. rxjs/Rx
  4. rxjs/add/observable/of
  5. rxjs/add/operator/catch

In the Angular codebase it is evident that lowercase characters are listed after capitalised or uppercase characters, hence: 'rxjs/Rx' is listed before 'rxjs/add/observable/of' and 'rxjs/add/operator/catch'

"Consider listing destructured imported symbols alphabetically."

import { TestBed, async, inject } from '@angular/core/testing';

import { AngularFireAuth } from 'angularfire2/auth';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/of';

Think of a "destructured imported symbol" as an exported symbol that has been extracted from its parent module. In this example AngularFireAuth, Observable, TestBed, async and inject are all destructured imported symbols.

Again, the order is alphabetised; uppercase first, then capitalised and then lowercase. Here is a great example from the Angular codebase:

import {CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, Directive, Inject, Injectable, Injector, Input, NgModule, Optional, Pipe, SkipSelf, ╔Ástringify as stringify} from '@angular/core';

There doesn't seem to be any particular order to importing services, pipes, models, directives or components, etc. looking at the Angular codebase

Note, modules in parent directories are imported after those closer to the module they are being imported into e.g.

import { AuthService } from './auth.service';
import { environment } from '../environments/environment';
import { abc } from '.../abc';

comments powered by Disqus