What is the difference Between ‘!:’ and ‘?:’ in TypeScript object definitions?

When having compiler option strictNullChecks: false

If you have strictNullChecks: false in your tsconfig.json then they are exactly the same since having strictNullChecks disabled means that all fields can have null or undefined as valid values.

When having compiler option strictNullChecks: true

class Employee {
   firstName: string;
   lastName!: string;
   middleName?: string;
}

firstName: string means that firstName must be a string. null or undefined are not valid values for firstName.

All uninitialized fields will have a default value of undefined, so this will result in an error Property 'firstName' has no initializer and is not definitely assigned in constructor

To silence the error you need to either change the declaration to firstName: string = 'Some default value' or add a constructor and assign a value for it in the constructor.

constructor() {
    this.firstName="some default value";
}

Now for the ! syntax. The lastName!: string syntax is similar to lastName: string in that it basically says that string is the only allowed type. null and undefined are not allowed. But it will silence the compiler about definite assignment error. Let’s say you have the following code.

   class Employee {
       firstName: string;
       lastName!: string;
       middleName?: string;

      constructor() {
          // This will silence the compiler about first name not initialized
          this.firstName="some default value";
          // The compiler cannot tell that lastName is assigned in init() function
          this.init();
      }
      
      private init(): void {
          this.lastName="some default value";
      }
    }

In the previous code, lastName is definitely assigned in the constructor via the this.init() call. However, the compiler cannot know that. So adding the ! is basically telling the compiler “shut up, I know what I am doing”. It is up to you then to ensure the correctness of your code.

About the middleName?: string syntax. This is similar to middleName: string | undefined; Since all values has a default value of undefined, the compiler won’t complain that middleName is not assigned.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)