typescripttype-declaration

Do we need type annotations even after adding type assertions in Typescript?


Do we really need to specify the type of a variable if we specify as in Typescript?

For example: The below code gives me same type of Object. But, I wanna know the correct way to do this.

const x: Student = {
  name: "John"
}

// is the above same as below

const x = {
  name: "John"
} as Student;

// or do we need to specify both

const x: Student = {
  name: "John"
} as Student;

export interface Student {
  name: string,
  id?: string
}


Solution

  • Type annotations and type assertions serve different but partially overlapping needs; it's rare indeed that you'd ever want to use both.


    A type annotation lets you explicitly choose the type of a variable. It is quite often unnecessary; without an explicit type annotation the variable's type can often be inferred by the type of its initializing value. If that value's type suffices for your needs, then an annotation is essentially redundant. If that value's type is insufficient, then an annotation is helpful. For example in

    const x = { name: "John" }
    /* const x: { name: string; } */
    

    the compiler infers the type of x as {name: string}. This is assignable to Student, and so depending on your use case it might suffice:

    function acceptStudent(s: Student) { }
    acceptStudent(x); // works
    

    But you should feel free to use an annotation if you prefer:

    const x: Student = {
      name: "John"
    }
    

    Type annotations are checked fairly strictly. If you annotate a variable with a type incompatible with its initializer, you'll get an error:

    const x: Student = { // error!
      id: "John",
    }
    

    A type assertion on the other hand lets you claim that an expression is of a certain type. This is used primarily when you know more about the type of an expression than the compiler can verify... you assert it, despite the compiler's inability to see that the assertion is true. Actually another use case is when you need to deliberately lie to the compiler about the type of an expression in order to proceed. Again it is also quite often unnecessary, since the compiler's inferred types for such expressions is usually reasonable. But there are times where you want to change the compiler's view about an expression's type:

    const x = {
      id: "John"
    } as Student; // no error
    

    Here the compiler does not complain, even though {id: "John"} is not a valid Student. It's close enough, though, for the compiler to accept your assertion.


    So it depends on what your needs are. The general advice here is roughly: prefer annotations over assertions, and prefer inference over annotations. If inference suffices, then use it. If not, then annotate. If that still doesn't work, then consider asserting (but be careful). And using both is almost certainly overkill. Once you assert the type of an initializing expression, that type will be the inferred type for the variable, and an annotation is therefore redundant.

    Playground link to code