Is there a difference between `as` type operator and classical typing in TypeScript?

Viewed 973

Is there any difference between

const b = 'test' as string; 

and

const b: string = 'test';
2 Answers

Simple answer Yes.

Explanation ( replacing const with let )

let b: string = 'test' we are explicitly saying we want b to be a string, so assigning anything other than a string to b will be a type error.

let foo = 'hello' as string Using as is called type assertion, we are telling typescript that , we want foo to be this particular type

( for the example you gave, they basically do the same thing ), but the type assertion can also be used in a situation like this

interface User {
  name: string;
  age: number;
  occupation: Array<string>
}
// doing this will cause an error, because the {} object does not 
// satisfy the requirement for User (structurally)
let currentUser: User = {}; 

// in this case what we will do is to use type assertion (typescript still does type checking as well
let currentUser: User = {} as User;

From your example the both code do the same thing, but type assertion and explicitly specifying the type of a variable are different

The difference is with normal assignment, the value being assigned must extend the type. But when using the as operator, either the value's type can extend the variable's type, or vice versa. Consider the following code:

type Foo = {
    foo: string;
}
let bar = {
    bar: 42
}
type Bar = typeof bar;

let foobar = {
    foo: 'hi',
    bar: 42
}

Note that types Foo and Bar are not compatible with each other. However, foobar is both a Foo and a Bar:

let foo: Foo;

foo = foobar; // ok, typeof foobar extends Foo
foo = {} as Foo; // ok. Foo extends {}
foo = bar as Foo; // fails, neither Foo nor Bar extends the other

bar = foobar; // ok, foobar extends Bar
foo = foobar; // similarly
foobar = bar; // fails, Bar doesn't extend typeof foobar

One of contexts where this makes a difference is the following (which passes type checking):

export default {bar: 0, whoops: 'invalid'} as Bar;

Although you do get intellisense when creating that object, you can still create properties that shouldn't be there. So a "workaround" which flags the type error is:

const bar: Bar = {bar: 0, whoops: 'invalid'};
export default bar;
Related