I'm just learning TypeScript and I'm a bit perplexed about the nature of any
. Take a look at this:
var x: any = 1;
var y = 1;
x = y;
y = x; // why does this not cause a compile-time error?
At first I understood any
to be the type without any promises - which is why the first assignment is reasonable to work - but it appears that in other contexts (the second assignment), it can be a type with all conceivable promises.
For example, this piece of insanity also compiles just fine:
undefined.foo
That's because undefined
is assumed to be any
, which is a type promising everything. Hmmm.
Contrast this to
var a : HTMLElement = new HTMLDivElement();
var b = new HTMLDivElement();
a = b;
b = a; // doesn't compile. phew.
Here we get what I would expect from assigning a more general thing to a more special thing in a strongly typed language: An error, as an explicit cast would be necessary:
b = <HTMLDivElement>a; // ah, you mean it's really a div...
In most cases where any
is used, I would expect something like unknown
, defined as
interface unknown { }
would be a better choice.
I first came across this problem as my code was using eval
to parse json. eval
returns any
, which means that TypeScript thinks that you can do everything with it, without any casts.
I think that's clearly wrong. Compare that issue to factories in other typed languages, such as C#:
(MyType)Activator.Create(typeof(MyType)) // cast is needed
Or C++:
// cast is needed in C++ (not in C, though I think it really should...)
(MyType*)malloc(size);
Whenever I have a function that produces something untyped, I would expect that I need to cast it before I can use it for anything.
So my questions are:
any
, something like the above unknown
, that is standard?any
featured so prominently and the other so hidden?But, implicit types do exist during program execution, and type conversion behaves similar to Javascript since the execution engine is, well, Javascript. But, you need to make explicit conversions in Typescript to humour the compiler, and probably, everyone else in your team.
JavaScript doesn’t have a concept of type casting because variables have dynamic types. However, every variable in TypeScript has a type. Type castings allow you to convert a variable from one type to another. In TypeScript, you can use the as keyword or <> operator for type castings.
But on the other hand, adding explicit type annotation is sometimes required, especially when TypeScript doesn’t have enough context to infer types eg. Function parameters: Further with the compiler flag –noImplicitAny in .tsconfig file that code produces an error:
In TypeScript, you can use the as keyword or <> operator for type castings. The following selects the first input element by using the querySelector () method: Since the returned type of the document.querySelector () method is the Element type, the following code causes a compiler error:
To the first question, the equivalent to unknown
is {}
, the empty type. The compiler will sometimes produce {}
when no other type can be computed (for example, in ['foo', 42]
, the element type was {}
before it became string|number
with the addition of union types).
Next, the reason any
is often mentioned is that the typical complaint about TypeScript is that it has too much type enforcement, rather than too little. JavaScript programmers just don't seem to be in to writing typecasts all the time. Obviously this is a matter of taste, but it is what it is.
This is all very much by design because a core scenario for TypeScript is to take an existing piece of JavaScript and add exactly as much type information as you want without getting tons and tons and tons of errors. Whenever TypeScript sees something without a type annotation where its type can't be inferred, it's going to use any
because that's the type that lets the most JavaScript compile without errors.
The undefined.foo
thing was fixed in version 1.1. It now correctly reports an error (the exact treatment of undefined
and null
in TypeScript is an interesting but separate discussion).
As Steve mentions, noImplicitAny
is there to help. It will raise errors when something is of type any
where there wasn't an explicit type annotation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With