内容简介:When implementing TypeScript in our projects, we strive to write the best typings we can. We might often feel like using theTheIn TypeScript, everything is assignable to any. It is often referred to as a
When implementing TypeScript in our projects, we strive to write the best typings we can. We might often feel like using the any type defeats the purpose of TypeScript, and rightfully so. There are also some other types worth knowing, and we might find them useful when trying not to use any , like the unknown . In this article, we also discuss never and void .
Any
The any type resembles how working with a pure JavaScript would be like. We sometimes might need to describe a variable that we don’t know the type of at all.
let uncertain: any = 'Hello world'!; uncertain = 5; uncertain = { hello: () => 'Hello world!' };
In TypeScript, everything is assignable to any. It is often referred to as a top type .
Writing the code in such a manner does not seem proper. It is unpredictable and hard to maintain. You might feel the need to use it when dealing with some third-party libraries that have no typings created for them, and you are not sure how they work. Also, using any might be a way to add TypeScript to your existing JavaScript codebase.
By using any , we undermine the ability of TypeScript to prevent us from causing trouble. There is no type-checking enforced, and therefore it might give you some headaches.
const uncertain: any = 'Hello world!'; uncertain.hello();
TypeError: uncertain.hello is not a function
And there you go, an error ready to ship to production! The above example is very vivid, but it could be more subtle.
const dog: any = { name: 'Fluffy', sayHello: () => 'woof woof' }; dog.hello();
TypeError: uncertain.hello is not a function
It would be beneficial to figure out some more detailed typings.
Unknown
The unknown type introduced in TypeScript 3.0 is also considered a top type , but a one that is more type-safe. All types are assignable to unknown , just as with any .
let uncertain: unknown = 'Hello'!; uncertain = 12; uncertain = { hello: () => 'Hello!' };
We can assign a variable of the unknown type only to any , and the unknown type.
let uncertain: unknown = 'Hello'!; let notSure: any = uncertain;
It does differ from any in more ways. We can’t perform any operations on the unknown type without narrowing the type.
const dog: unknown = getDog(); dog.hello();
Unable to compile TypeScript: Property ‘hello’ does not exist on type ‘unknown’.
Narrowing down the unknown with type assertions
The above mechanism is very preventive but limits us excessively. To perform some operations on the unknown type, we first need to narrow it, for example, with a type assertion.
type getDogName = () => unknown;
const dogName = getDogName(); console.log((dogName as string).toLowerCase());
It the code above, we force the TypeScript compiler to trust that we know what we are doing.
A significant disadvantage of the above is that it is only an assumption. It has no run-time effect and does not prevent us from causing errors when done carelessly.
const number: unknown = 15; (number as string).toLowerCase();
TypeError: number.toLowerCase is not a function
The TypeScript compiler receives an assumption that our number is a string, and therefore it does not oppose treating it as such.
Using control-flow based narrowing
A more type-safe way of narrowing down the unknown type is to use a control-flow narrowing.
The TypeScript compiler analyses our code and can figure out a narrower type.
const dogName = getDogName(); if (typeof dogName === 'string') { console.log(dogName.toLowerCase()); }
In the code above, we check the type of the dogName variable in the run-time. Therefore, we can be sure that we call the toLowerCase function only if the dogName is a variable.
Aside from using typeof , we can also make use of instanceof to narrow the type of a variable.
type getAnimal = () => unknown;
const dog = getAnimal(); if (dog instanceof Dog) { console.log(dog.name.toLowerCase()); }
In the code above, we make sure that we call dog . name . toLowerCase only if our variable is an instance of a certain prototype. TypeScript compiler understands that and assumes the type.
If you want to know more about prototypes, check out Prototype. The big bro behind ES6 class
There is currently an interesting suggestion stating that TypeScript should also use the in operator when narrowing types to assert property existence. If you’re interested, check out this issue in the TypeScript repository .
A workaround provided by Tom Crockett is to use a custom hasKey type guard.
const dog = getAnimal(); if (typeof dog === 'object' && hasKey('name', dog)) { console.log(dog.name); }
Differences between Void and Never
The void and never types are often used as return types of functions. To avoid confusion, let’s compare them.
Void
The void type acts as having no type at all.
function sayHello(): void { console.log('Hello world!'); }
It is useful to indicate that we are not supposed to use the return value of the above function. We can spot the difference between the void and undefined here:
The void type is common in other languages like C++, where it serves a similar purpose.
Never
The never type indicates that a function never returns . We sometimes refer to it as the bottom type .
A typical example is when a function always throws an error:
function throwUserNotFoundError(userId: number): never { throw new Error(`User with id ${userId} is not found`); }
Another example is when the function has a loop that never ends.
function renderGame(game: Game): never { while (true) { game.renderFrame(); } }
Also, the TypeScript compiler asserts the never type if we create an impossible type guard:
const uncertain: unknown = 'Hello world!'; if (typeof uncertain === 'number' && typeof uncertain === 'string') { console.log(uncertain.toLowerCase()); }
Property ‘toLowerCase’ does not exist on type ‘never’.
Summing up both never and void :
- A function that does not return any value explicitly has a return value of undefined . To indicate that we ignore it, we use the void return type
- A function that never returns at all due to some reasons has a return type of never
Summary
In this article, we’ve gone through the differences between any and unknown . A conclusion from comparing the above is that the unknown type is a lot safer because it forces us to do additional type-checking to perform operations on the variable. We’ve also gone through the never and void types. By doing so, we differentiate functions that don’t return values from the ones that don’t return at all.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript修炼之道
波顿纽威 / 巩朋、张铁 / 人民邮电 / 2011-11 / 29.00元
《JavaScript修炼之道》是JavaScript的实战秘籍。作者将自己多年的编程经验融入其中,不仅可以作为学习之用,更是日常JavaScript开发中不可多得的参考手册,使读者少走很多弯路。《JavaScript修炼之道》的内容涵盖了当今流行的JavaScript库的运行机制,也提供了许多应用案例。《JavaScript修炼之道》针对各任务采取对页式编排,在对各任务的讲解中,左页解释了任务的......一起来看看 《JavaScript修炼之道》 这本书的介绍吧!