Ship internal tools in hours, not weeks. Real auth, users, jobs, audit logs, and cohesive UI included. Early access $249 $499 → [Get it now]

How to configure Angular strict mode

Configuring Angular strict mode is a vital step for ensuring long-term maintainability and catching potential bugs during development rather than in production. As the creator of CoreUI, with over 25 years of experience in software engineering, I have seen how strict typing prevents entire classes of runtime errors in complex UI ecosystems. The most efficient way to achieve this is by enabling the strict flag in your TypeScript configuration and leveraging Angular’s specialized template type checking. This proactive approach leads to cleaner, more robust codebases that are significantly easier to refactor and scale over time.

Enable Angular strict mode by setting the strict property to true in your tsconfig.json and angular.json configuration files to enforce rigorous type checking.

Enabling Strict Mode in New Projects

When starting a fresh project, the easiest way to ensure compliance is by using the Angular CLI flag. This automatically configures all necessary files with the recommended strict settings.

# Create a new project with strict mode enabled
ng new my-strict-app --strict

This command modifies the angular.json file and the root tsconfig.json. It sets the strict flag to true within the compilerOptions, which activates a suite of TypeScript checks. Note that strict mode has been the default since Angular 12, so if you are on a modern version, this flag is likely already active in your project.

Configuring TypeScript Strict Compiler Options

In an existing project, you must manually update your tsconfig.json file. The strict flag is a shorthand for several individual flags that enforce better code quality.

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true
  }
}

By setting strict: true, you enable all the flags listed above. For instance, strictNullChecks ensures that you explicitly handle cases where a value might be null or undefined. This is crucial when building reliable interfaces with our Angular Dashboard Template, where data consistency is paramount for dashboard accuracy.

Activating Angular Template Type Checking

Angular provides its own set of strictness flags specifically for HTML templates. These are defined under the angularCompilerOptions section in your tsconfig.json.

{
  "angularCompilerOptions": {
    "strictTemplates": true,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictInputTypes": true,
    "strictOutputEventTypes": true,
    "strictDomEventTypes": true
  }
}

Setting strictTemplates to true is the most impactful change. It forces the Angular compiler to check the types of your property bindings and event listeners within your HTML files. This prevents common errors like passing a string to a component input that expects a number, or referencing a non-existent property in a structural directive like *ngIf.

Enforcing Strict Dependency Injection

Strict injection parameters ensure that the compiler verifies the types of dependencies provided to your constructors. This prevents runtime errors caused by missing providers or type mismatches during service injection.

import { Injectable } from '@angular/core'

@Injectable({
  providedIn: 'root'
})
export class DataService {
  // Strict mode ensures 'apiUrl' must be typed and initialized
  private readonly apiUrl: string = 'https://api.coreui.io'

  constructor() {}
}

In strict mode, if you define a constructor parameter that Angular cannot resolve, it will throw a compile-time error. This guarantees that every dependency is accounted for before the application even boots up, making wiring up complex business logic far safer.

Handling Strict Property Initialization

One of the most frequent challenges in strict mode is handling class properties that aren’t initialized in the constructor. TypeScript will flag these as errors if strictPropertyInitialization is active.

import { Component, OnInit } from '@angular/core'

@Component({
  selector: 'app-user',
  template: '<div>{{ username }}</div>'
})
export class UserComponent implements OnInit {
  // Using the non-null assertion operator or a default value
  username!: string

  ngOnInit() {
    this.username = 'CoreUI_User'
  }
}

You can resolve this by providing a default value, making the property optional with ?, or using the non-null assertion operator ! if you are certain the value will be assigned before use (e.g., via a lifecycle hook). This level of discipline ensures that your components remain predictable and free from “undefined” errors.

Strict Mode and Form Validation

Strict mode significantly improves the developer experience when working with forms. By enforcing types on form controls, you can catch errors early in the data-handling pipeline.

import { FormControl, FormGroup, Validators } from '@angular/forms'

// Define a strictly typed form group
const loginForm = new FormGroup({
  email: new FormControl<string>('', {
    nonNullable: true,
    validators: [Validators.required]
  }),
  password: new FormControl<string>('', {
    nonNullable: true
  })
})

Using the nonNullable option ensures that the form control value never reverts to null when the form is reset. This aligns perfectly with the CoreUI Validation patterns, where we emphasize clear state management and user feedback. Strict mode makes your validation logic much more transparent and less prone to edge-case failures.

Incremental Adoption in Large Codebases

If you are working on a legacy project, jumping straight to full strict mode can be overwhelming. I recommend an incremental approach by enabling individual flags one by one.

{
  "compilerOptions": {
    // Start with basic strictness
    "noImplicitAny": true,
    // Add null checks later
    "strictNullChecks": false
  }
}

Start with noImplicitAny to force type definitions, then move to strictTemplates for your UI logic. This allows your team to fix errors in manageable batches without halting feature development. In my experience building CoreUI, this phased migration is the most successful strategy for large-scale enterprise applications.

Best Practice Note:

At CoreUI, we always develop our components with full strict mode enabled. This ensures that the library is as reliable as possible for the millions of developers who rely on it. While strict mode might feel restrictive at first, it actually speeds up development by providing better IDE autocompletion and preventing the “save-and-refresh” cycle to catch simple typos. For the best results, always pair strict mode with a robust linting configuration to maintain a consistent code style across your entire team.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author