DEV Community

Kento Honda
Kento Honda

Posted on

Void and Never in TypeScript

Intro

Currently, I am learning TypeScript by reading the book, "Learning TypeScript" (written by Josh Goldberg), to comprehend TypeScript and to gain in-depth knowledge for it.

In Chapter 5 of this book, I reviewed how void and never types work in TypeScript function types and how they are properly distinguished from each other.

Many beginners learning TypeScript may not have a solid understanding of these two return types: void and never. Therefore, I have summarized the fundamental concepts of these types briefly in this article.

Before diving into main topic...

In TypeScript, we can declare types of functions to them as same as type annotations to variables. They are called Function types and include the types of their arguments and those of their return value.

Function types are generally defined as callback functions. Here is a code snippet showing an example of Function type.

// Declare a Function type with two parameters having number type, and a returned value having number type as well 
type SumOfTwoNumbers = (num1:number,num2:number) => number
Enter fullscreen mode Exit fullscreen mode

Because of the declaration of Function type (in this case, twoSumOfNumbers type), we could easily interpret what types of value should we pass to the function with twoSumOfNumbers type. We could also guess what type of value will be returned from that function.

When it comes to void and never, they have been recognized the part of Return types in Function types and are necessary in some cases of them for the sake of explicit return types.

So now, let's get started.

Void type

Void type (void return) stands for the absence of return value in a function. In other words, functions with void type as Return type imply that they have no value to return.

That also means void type ignores any returned value from a function.

// Declare a Function type with void
let printString: (str:string) => void;

// This function returns nothing
printString = (str) => {
  console.log(str)
}
printString("Return string")  // Output: "Return string"
Enter fullscreen mode Exit fullscreen mode

Difference between void and undefined

When talking about void type, it is unavoidable to see the difference between void and undefined in terms of return types. That is because both of them seem to be working the same, but technically not.

// a function with void return type
function sampleFuncWithVoid(str:string): void {
  return; // OK
}

// a function with void return type and return string type
function sampleFuncWithVoidAndReturnVal(str:string): void {
  return str;   // Error: Type '"Return something"' is not assignable to type 'void'
}

// a function with undefined return type
function sampleFuncWithUndefined(): undefined {
  return;   // OK
}

// a function with undefined return type and return string type
function sampleFuncWithUndefinedAndReturnVal(str:string): undefined {
  return str;    // Error: Type '"Return something"' is not assignable to type 'undefined'
}
Enter fullscreen mode Exit fullscreen mode

As you can see from the codes above, the way to work for void type and undefined type looks the same.

But the truth is that void ignores the return value coming from the callback function, while undefined is literally one of the return types in the function.

// Declare a variable with a function type returning undefined
let createAnimalArr:(arr:string[]) => undefined;

/* Error: Type '(arr: string[]) => number' is not assignable to type '(arr: string[]) => undefined'. */
createAnimalArr = (arr:string[]) => {
   // unshift method in JavaScript returns the value with number type
   return arr.unshift('Seal')
}
Enter fullscreen mode Exit fullscreen mode

Let's replace undefined type to void type and see how it goes. I use the same function above and turn out to work fine. That is either because void type does not use any returned value at all or because it allows having any type values to return values from functions (finally they are all ignored).

// Declare a variable with a function type having void return
let createAnimalArr:(arr:string[]) => void;

// Ok: void type ignore returned value (number)
createAnimalArr = (arr:string[]) => {
   return arr.unshift('Seal')
}

// Ok: number value is allowed in createAnimalArr but is ignored in the end
createAnimalArr = (arr:string[]) => {
   arr.unshift('Seal')
}
Enter fullscreen mode Exit fullscreen mode

Never type

Never type (never return) refers to the type indicating that as the name suggests, functions with never type as Return type never return value. (e.g. a function throws an exception, or that enters an infinite loop)

// Declare a Function type with never
type NeverFunc = (str:string) => never;

// A function that throws error so return type should be never
function neverPrint(str:NeverFunc) => {
  throw new Error(`Never returns ${str}`)
}
Enter fullscreen mode Exit fullscreen mode

In general, Never type is not used in professional TypeScript settings. So we do not have to care about it too much, but it is worth it to comprehend the correct meaning of Never return.

Conclusion

In summary, void type is utilized for functions that do not return a value because void ignores any returned values at all, while functions that never complete normally or for values that can never exist use never type.

Writing this article allowed me to dive deeper into the concepts of TypeScript's return types in functions. However, I found it challenging to interpret the precise differences between void and undefined as return types.

Moving forward, I plan to experiment with more possible use cases for void and never types to become more comfortable using them.

References

Top comments (0)