Never
TypeScript introduces a type in order to indicate instances where something should never occur. A typical example of this is where a function will always throw an error, and as such will never return a value. Consider the following code:
function alwaysThrows() {
throw "this will always throw";
return -1;
}
Here, we have defined a simple function named alwaysThrows. The first line of this function throws an error, and as such, the second line of this function will never be executed. This is valid TypeScript, but does indicate that there is a flaw in our logic, as the return statement will never be executed. We can guard against this by using the return type of never in our function definition as follows:
function alwaysThrows(): never { throw "this will always throw"; return -1; }
Here, we have used the never keyword to indicate that this function will never return a value. The compiler will now generate an error, as follows:
error TS2322: Type '-1' is not assignable to type 'never'
The error message is clearly stating that the function, which should return never, is trying to return the value -1. We have clearly stated the end effect of our function, which is that it will never return anything, and the compiler is helping us to enforce this.
A much more practical use of the never keyword is to trap flaws in our code logic that we know should never occur. As an example of this, consider the following code:
enum TestNeverEnum { FIRST, SECOND } function getEnumValue(value: TestNeverEnum): string { switch (value) { case TestNeverEnum.FIRST: return "First case"; } let returnValue: never = value; }
Here, we have defined an enum named TestNeverEnum that has two values, FIRST and SECOND. We then define a function named getEnumValue that is designed to return a string based on the enum value passed in. After the switch statement, we define a value named returnValue, of type never, and assign the incoming value argument to it. This code will generate a compile error as follows:
error TS2322: Type 'TestNeverEnum.SECOND' is not assignable to type 'never'
What is happening here is that our switch statement is not handling the case of TestNeverEnum.SECOND. This logic flaw means that the flow of code will actually drop down to the let returnValue : never = value line. As we have used never as a type here, the compiler is generating the error. This code needs to be fixed as follows:
function getEnumValue(value: TestNeverEnum): string { switch (value) { case TestNeverEnum.FIRST: return "First case"; case TestNeverEnum.SECOND: return "Second case"; } let returnValue: never = value; }
Here, we have added a case statement for the TestNeverEnum.SECOND value, and therefore, the last line of code will never be executed.
Using never as a type in this instance helps us to guard against logic flaws in our code. In large and long-lived projects, this can occur quite often. Enums, in particular, are constantly getting added to as project requirements grow. By using never in these instances, we can trap logic errors where we have modified an enum, but have not added the correct switch cases correctly.