4

The code:

class Cat extends Animal { tag! : 'cat' }

What does "!" mean after tag declaration? How is it different from just tag?

RandomB
  • 3,367
  • 19
  • 30
  • 6
    Possible duplicate of [In Typescript, what is the ! (exclamation mark / bang) operator when dereferencing a member?](https://stackoverflow.com/questions/42273853/in-typescript-what-is-the-exclamation-mark-bang-operator-when-dereferenci) – JoSSte Nov 26 '19 at 15:00
  • Definitely a duplicate. – IloneSP Nov 26 '19 at 15:01
  • I don't know, IMHO it's not a duplication, because the bang as operator removes "nullity", "undefinity" when you are sure in this, but in declaration, I don't know what it is – RandomB Nov 26 '19 at 15:02
  • Even more, 3 cases: `tag: int`, `tag!: int`, `tag?: int`. What is the difference between 1st and 2nd ? – RandomB Nov 26 '19 at 15:05
  • By removing this operator, the following typescript error will popup `Property 'tag' has no initializer and is not definitely assigned in the constructor.(2564)` therefore, you will shut the compiler up to complain about non constructor initialized properties, which is kind of a duplicate. – r3dst0rm Nov 26 '19 at 15:05
  • @r3dst0rm I have not an error in `class Cat extends Animal { tag : 'cat' }` declaration after removing of "!" – RandomB Nov 26 '19 at 15:07
  • Your three cases: the first is simply defining a property tag with type int. The second makes the compiler silent about the possibility that it isn't initialized inside the constructor. The third makes the property optional and therefore either a int or undefined – r3dst0rm Nov 26 '19 at 15:07
  • Then it might be initialized inside your constructor? – r3dst0rm Nov 26 '19 at 15:08
  • Hm, maybe I miss something, but I don't see difference, I tried both cases and tsc did not show any error. Would you like to show some short example? – RandomB Nov 26 '19 at 15:11
  • 1
    For sure, as the code is not a complete example I just added a bit more of code, like the Animal class/interface. https://codesandbox.io/s/k1i9q – r3dst0rm Nov 26 '19 at 15:14
  • Oh, I got the difference. @r3dst0rm if you want to add it as the answer, I will mark it as valid answer – RandomB Nov 26 '19 at 15:17
  • This is definitely not a duplicate. Bang operators in property declarations have a different implication than in a function parameter list. See my comment to the response below. – Daniel Handojo Nov 16 '21 at 17:45

1 Answers1

5

Let's look at an example - imagine we have the following code:

interface Animal {
    tag: string;
}

class Cat implements Animal { tag: 'cat' }
class AnimalClass {
    tag: string | undefined;
}

class Dog extends AnimalClass { tag: 'dog' }

Both code snippets would throw the following: Property 'tag' has no initializer and is not definitely assigned in the constructor.(2564).

This is a feature of TypeScript added in 2.7.2 where it includes a strict class check, where all properties should be declared inside it's constructor.

By adding a bang sign !, you will override this behavior and tell the compiler you "know", that it is being initialized correctly and won't be undefined later on.

Also you can disable it by setting "strictPropertyInitialization": false inside your compiler options. Or you initialize the property where it should be initialized (according to TypeScript):

class Dog extends AnimalClass { 
    tag: string;

    constructor() {
        super();
        this.tag = "";
    }
}
r3dst0rm
  • 1,876
  • 15
  • 21
  • https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html https://github.com/prettier/prettier/issues/3561 – Daniel Handojo Nov 16 '21 at 17:45