195

Is there any difference between what the TypeScript spec calls a type assertion:

var circle = <Circle> createShape("circle");

And the newer as operator:

var circle = createShape("circle") as Circle;

Both of which are typically used for compile-time casting?

mk.
  • 11,360
  • 6
  • 40
  • 54

3 Answers3

229

The difference is that as Circle works in TSX files, but <Circle> conflicts with JSX syntax. as was introduced for this reason.

For example, the following code in a .tsx file:

var circle = <Circle> createShape("circle");

Will result in the following error:

error TS17002: Expected corresponding JSX closing tag for 'Circle'.

However, as Circle will work just fine.

Use as Circle from now on. It's the recommended syntax.

David Sherret
  • 101,669
  • 28
  • 188
  • 178
  • 1
    In my code, I tried using a string value as a key for returned JSX in the map function but I did get a type error over and over. The old casting method didn't work but only when used 'as' operator the error disappeared! <3 – imvanzen Jul 24 '22 at 14:19
43

From Wiki page: "What's new in TypeScript [1.6]":

New .tsx file extension and as operator

TypeScript 1.6 introduces a new .tsx file extension. This extension does two things: it enables JSX inside of TypeScript files, and it makes the new as operator the default way to cast (removing any ambiguity between JSX expressions and the TypeScript prefix cast operator). For example:

var x = <any> foo; 
// is equivalent to:
var x = foo as any;
MartyIX
  • 27,828
  • 29
  • 136
  • 207
  • 7
    is any different on this two? ```var x = foo as any; var x: any = foo;``` – yusung lee Oct 23 '20 at 06:46
  • 2
    @yusunglee better answer to your question : https://stackoverflow.com/questions/69220403/is-there-a-difference-between-as-type-operator-and-classical-typing-in-typescr?noredirect=1#comment122344292_69220403 – TheSmartMonkey Sep 17 '21 at 11:55
1

One important difference is the precedence of these two operators. For example in AssemblyScript which you may consider like a stricter TypeScript, you may more often feel the need to decide on using one or the other.

const COPY_FROM : usize = <u64>start >>> 6 as usize;

start which is a number type casted into unsigned 64 bit integer, right shifted by 6 bits and the result is casted to <usize> pointer type. Which is exactly the desired behaviour.

However

const COPY_FROM : usize = <u64>start >>> <usize>6;

is not what we want and wouldn't even compile. Yet,

const COPY_FROM : usize = <usize>(<u64>start >>> 6);

is harder to read and not so pretty.

However as I understand for some unknown reason the precedence of as is not low enough to be a trailing operator. For example had the above code be like;

const COPY_FROM : usize = <u64>start & 63 as usize; // start % 64

then it would either throw or yield wrong result as seemingly the precidence of as is higher than the & operator. So we best be careful using it.

Redu
  • 25,060
  • 6
  • 56
  • 76