Why does type "any" exist in Typescript?

Asked

Viewed 126 times

5

I’m studying Typescript and I got to the part about the guy any. What I understand is that the any is used when the type of the value that the variable will have.

But if that’s the case, the two lines of code below are not the same?

let var1: any = "Hello World"; 
let var2 = "Hello World"; // Código JS

Why the any exists in TS? There is some difference, even if minimal, between using the any and not to declare any type for the variable?

  • 4

    I believe it is to interface with Javascript code vanilla, which can send or receive values mixing types.

  • And I asked myself that same question about unknown....

  • @Cmtecardeal, on the unknown: How type "Unknown" works in Typescript?.

3 answers

9

The two lines give the same result, but they are not the same thing. There is an explicit semantics in the first line, which is more readable and shows that the intention is precisely this.

If Typescript is a language with static typing in the first place, letting dynamics work (gradual typing), the ideal is that this dynamism is explicit. If you leave it implicit it could be that the code came from Javascript that has no type, or the code was made sloppy.

There is a option which controls the behavior of the second line of how it will be interpreted by the compiler.

The second way does not exist to communicate with Javascript because after compiled the first line is identical to the second in JS target. In fact all types are lost after compiled.

If the question is because there is such an open type, then it is to give more flexibility, because it has problem that is easier to describe having a dynamic type, and also because this problem may have to communicate with JS that waits like this. But it’s something collateral.

There are several cases that the semantics of the type is to be dynamic, can have any value in that variable, and has even more when working together with codes in JS where all variables are any.

The second form written in TS is lazy. Even a type of union can be better than any when you may have two or more specific types, but not all types. In an essentially static typing language spell out the type always, until it can be anyone.

See more: What is typing style?.

8


To understand the motivation of any, it is necessary, rather, to understand one of the fundamental principles of Typescript, which is to enable gradual adoption.

For a long time, the Javascript ecosystem had no efficient means of checking, statically, the scripts and "programs" that were developed with this language. As the dynamic typing of Javascript, allied to the various quirks of the language, were (and still are) the source of many bugs, Typescript was created to ensure greater robustness to development. Some say, quite emphatically, that static types help a lot in this case - and although that’s not the case, I agree.

Naturally, cases would arise in which a codebase, originally implemented in Javascript, would have its developers choose to migrate it to Typescript. The poblema is that, depending on the size of the code base, the task is often difficult. Hence the need for mechanisms to ensure a gradual adoption of Typescript more flexible.

The any is one such mechanism. It is a means of giving pliability to the programmer. The use of any it is as if the programmer speaks to the compiler the following:

I want you, compiler, do not worry about this value. To it I assign this joker type, any, that basically allows me to do anything with it without you filling me with patience.

That’s it.

Think about the any as the union of all types of Typescript. A type value any accepts anything and therefore is nothing safe. By using any, You give up, for convenience, all the security that Typescript gives you.

And just to emphasize the definition a little more, let’s look at the typescript documentation, what it says:

Typescript also has a special type, any, that you can use whenever nay want a specific value to cause errors of type-check.

When a value is of the kind any, you can access any of its properties (which will also be of the type any), call it as a function, assign it to values of any kind - in short: anything that is not syntactically illegal.

Reiterating, see that the use of any gives up the security that Typescript offers. Therefore, in more recent versions of Typescript, the unknown, that does something similar, but with a little more security.

Still on the any, documentation says more:

When you do not explicitly specify a type and Typescript can’t make it out by context, the compiler will use any as default. Assuming the option noImplicitAny is disabled (which is the default behavior, although less secure).

With this, we can allude to the question code example:

let var1: any = "Hello World"; 
let var2 = "Hello World";

They are different things. In the above case, var1 will have the type any. Already var2, due to the possibility of Typescript inference, you will have the type string. So it’s the same as:

let var1: any = "Hello World"; 
let var2: string = "Hello World";

This is one of the cases where Typescript can safely infer the type of the variable. And this is obvious to the compiler, so much so that no warning is issued or any is assumed by default. You are assigning to var2 a string, which is in the code itself. In this type of case, it is clear to Typescript that that variable at all times will be a string (see that it will always be assigned a literal string). Therefore, it is said that string is the guy inferred.

See the difference between this passage, in which there is no possible inference and any is assumed; and this, with the option noImplicitAny and error has been issued.

This is one of the powers of Typescript, which has relatively good inference ability. As we have seen before, when inference is not possible, by default, any will be used, but there is an option that prohibits this behavior, requiring the programmer, in this type of case, to clarify the type. It is about noImplicitAny.

So you have to be careful to know when the guy is any and when the guy is inferred. If you are using a supported editor (like Vscode), when you hover over a value, you can see the type it takes. Then it’s easy to know.

In summary, the any is a joker - but you have to be careful not to confuse this "joker" with the inference.

The inference, when allied to the option noImplicitAny, is something that ensures security and robustness to the code. It’s a compiler convenience so you don’t always have, where it’s obvious by context, to spell out the type manually.

The any is a escape-Hatch which allows you to give up a certain security for flexibility. It is a convenience that is worthwhile on occasions such as gradual migration. When Typescript is being used from day zero, it rarely makes sense, since it gives up security.

  • So it means, by inferring that the guy is string, i cannot change the variable value to number, for example. That’s it?

  • Yes, @Jeanextreme002. Once the type has been inferred, a change to the type is not allowed. See here. Inference is something very powerful, since, at the same time it brings some security, allows the programmer not to waste time typing types already safely informed by the context. No wonder more modern languages, like Rust, and languages originally without inference (like C#, by var) have adopted this resource.

1

Simply:

let var1: any = "Hello World";

var1 can be reset as any other object and typescript will not fight with you pq set it when using any.

let var2 = "Hello World";

On that line Oce already implicitly states var2 as a string and trying to reset this value to a number (for example) would already give an error. In typescript, if Voce does not set a type in the declaration of an object, typescript will set the type of that object automatically.

Other examples:

let foo = { cc: 'bar' }; // o tipo de foo seria: {cc: string}
foo = { cc: 'asdf', dd: 'sdfsd' }; // erro
foo = 'test'; // erro
foo = { cc: 22 }; // erro
foo = { cc: 'qualquer string' }; // certo
let foo2 = [22]; // o tipo de foo2 seria: string[]
foo2 = { cc: 22 }; // erro
foo2 = ['55', 66, 77]; // erro
foo2 = [55, 66, 77]; // certo

now

let foo3: any = [22]; // o tipo de foo3 seria: any
foo3 = { cc: 22, tt: 'test' }; // certo
foo3 = 'test'; // certo
foo3 = [55, 66, 77]; // certo

Browser other questions tagged

You are not signed in. Login or sign up in order to post.