Unknown & Never in TypeScript

Unknown & Never in TypeScript

There are 2 other main types that are important to be familiar with. These types are not as common as other types, but they still have their uses. The first of these types is unknown. For example, suppose I have a variable like this:

let userInput: unknown;

I've assumed here that we don't know what the user is going to enter in this field, so I've given it the type unknown. As it turns out, we can store any value in unknown without error:

let userInput: unknown;
userInput = 5;
userInput = 'Max';

If I run tsc app.ts now, typescript compiles my code without any errors. You may ask yourself what is the difference between any and unknown. Yes, these two types are very similar, but they have an interesting difference. Suppose we have another variable whose type is string:

let userName: string;

If we assign such a variable to userInput, we will encounter an error:

let userInput: unknown;
let userName: string;
userInput = 5;
userInput = 'Max';
userName = userInput;

In the code above, Typescript immediately draws a red line under the last line of the code and gives us an error:

Type script error for type unknown

I think the reason for this error is clear to you. The userName variable requires a string value, but it is not clear whether userInput is a string or takes another value! The interesting thing is that if I set userInput to any I don't get any error:

let userInput: any;
let userName: string;
userInput = 5;
userInput = 'Max';
userName = userInput;

This code for typescript is completely correct! why Because any is the most flexible type in the Typescript language and disables all type checks. In other words, if you use any for a variable or parameter, you lose the ability to specify the type for it because TypeScript doesn't bother to check it anymore. In the case of unknown, it works a bit more strict, and for example in the previous code, if we want to solve the error, we must explicitly check and make sure that the userInput type is a string:

let userInput: unknown;
let userName: string;
userInput = 5;
userInput = 'Max';
if (typeof userInput === 'string') {
  userName = userInput;
}

By doing this, we don't see any more errors and we can easily compile the codes. Now Typescript understands that I am sure of the type of userInput variable and I have set it equal to username by my conscious decision. The general rule is that if you use unknowns, you must explicitly use an if condition to assign them to other variables to tell TypeScript that you are sure of its type.

This is why, in general, unknown is a better choice than any, and if you are not sure about the type of your variable or parameter, choose unknown instead of any. Of course, this does not mean using unknown indiscriminately, and you should still avoid using it as much as possible. For example, one of the better methods is to use union types.

Our next type is never. never in TypeScript is another type that can be returned by functions. For example, suppose we have a function as follows:

function generateError(message: string, code: number) {
}

The task of this function is to generate an error and it takes two parameters, the first of which is a string (error message) and the second is a number (error code). I want to throw an error in this function and as we know this feature is available in javascript. We can throw anything we want as an error:

function generateError(message: string, code: number) {
  throw { message: message, errorCode: code };
}

As you can see, I have thrown an object that has two properties: message and errorCode, and the values ​​of these properties are equal to the parameters passed to the function. Now we call it like any other function:

function generateError(message: string, code: number) {
  throw { message: message, errorCode: code };
}
generateError('An error occurred!', 500);

The result of calling this function is an error in the browser console:

Throwing an error in the browser console

Having helper functions in this way may be useless at first glance, but in big and real projects, such functions are always used. In these types of projects, throwing errors manually is a tedious task, especially since the errors of these types of projects are not one-line and simple like the above code, and they contain all kinds of information and other settings.

You know that the function above returns the void value because it does not have a return statement, which is correct to some extent, but if we want to check it from a completely technical point of view, we must say that this function returns never! why Because this function "never" creates a value to return. For example, if we want to store its value in a variable:

function generateError(message: string, code: number) {
  throw { message: message, errorCode: code };
}
const result = generateError('An error occurred!', 500);
console.log(result);

And then I compile the code with tsc app.ts, nothing is displayed in the console part of the browser (except the error we threw with throw). Note that no value such as undefined is returned. The generateError function never produces any value, so it can be said that the return type of this function is both void and never.

If you move your mouse over generateError, it will tell you that the type of the function is void, because the never type is a little newer and was not in the original versions of the Typescript language, so in this case, the same void is usually placed for such values, unless you yourself Manually set it to never:

function generateError(message: string, code: number): never {
  throw { message: message, errorCode: code };
}

Another example of a never type function is infinite loops:

while (true) {}

This loop always runs and never has time to return anything, so its type is never in TypeScript.

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center