Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: Implicit cast from any to everything?

Tags:

typescript

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:

  1. Is there the analogous to any, something like the above unknown, that is standard?
  2. If so, why is any featured so prominently and the other so hidden?
  3. Has this issue been raised somewhere? Is there a discussion anyone can link to?
like image 346
John Avatar asked Nov 22 '14 19:11

John


People also ask

Do implicit types exist in typescript?

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.

What is the difference between typescript and JavaScript type casting?

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.

When to add explicit type annotations in typescript?

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:

How to cast an element to another element in typescript?

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:


1 Answers

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.

like image 82
Ryan Cavanaugh Avatar answered Oct 24 '22 06:10

Ryan Cavanaugh