What’s the "Never" type for?

Asked

Viewed 459 times

4

Today I was asked what the guy is for never Typescript, but it got confused for me. It just serves to say that it does not return anything? What’s the difference to the void?

2 answers

3


never

The guy never indicates that the function never returns something. That is, functions that generate an error or generate a loop have their return defined as never. Quoting the documentation, in free translation:

The guy never represents the type of values that never occur. By example, never is the type of return to a function or to a Arrow Function that always casts an exception or one that never returns; variables also acquire the type never when narrowed by any kind of protection that can never be true.

The guy neveris a subtype of and may be assigned to all types; in however, no type is a subtype of, or can be attributed to, never (except the very never). Even any is not attributable to never.

// Uma função retornando "never" deve ter um ponto final inacessível
function error(message: string): never {
    throw new Error(message);
}

// O tipo de retorno inferido é "never"
function fail() {
    return error("Aconteceu um erro!");
}

// Uma função retornando "never" deve ter um ponto final inacessível
function infiniteLoop(): never {
    while (true) {
    }
}

Examples

A difference between the void and the never is that the guy void can receive the value undefined, as the guy never cannot receive any value (only itself, never).

I left the example below in Codesandbox so that it is possible to view the results and errors of lint.

function funcaoVoid(): void {
  console.log("Executando funcaoVoid");
}

function funcaoNeverLoop(): never {
  // Essa função gera um erro de loop infinito
  console.log("Executando funcaoNeverLoop");
  while (true) {}
}

function funcaoNeverErro(): never {
  console.log("Executando funcaoNeverErro");
  throw new Error("Erro gerado");
}

// Void
console.log('Chamada "funcaoVoid()":', funcaoVoid());

// Never - Loop
try {
  console.log('Chamada "funcaoNeverLoop()":', funcaoNeverLoop());
} catch {
  console.log('A função "funcaoNeverLoop()" foi chamada e entrou no "catch"');
}

// Never - Error
try {
  console.log('Chamada "funcaoNeverErro()":', funcaoNeverErro());
} catch {
  console.log('A função "funcaoNeverErro()" foi chamada e entrou no "catch"');
}

// Veja o erro em attr
const attr: never = undefined;
const attr2: void = undefined;

// O console.log() funciona para attr pois a tipagem em TS é apenas em tempo de compilação.
console.log(attr, attr2);

The results in the console are:

Executando funcaoVoid
Chamada "funcaoVoid()": undefined
Executando funcaoNeverLoop 
A função "funcaoNeverLoop()" foi chamada e entrou no "catch" 
Executando funcaoNeverErro 
A função "funcaoNeverErro()" foi chamada e entrou no "catch" 
undefined undefined
  • 1

    I can’t see a use and I’ve never even seen code using never, but it seems that it would be used only in function that would treat a message and then issue an error. Would it have any use with this type? First time I heard of him and I thought it was kind of weird, because I thought void was enough. Or maybe the Intellisense show that the function is of the type never to draw the developer’s attention to some error that generates infinite loop... I do not know.

  • 1

    From the research I did on the Internet, for functions I only found these two examples, being that of generating error the most useful case (a function that generates a standard error for you). I think the best thing to gain from it is to call it that and you notice that it’s like never and already be able to understand in time what can happen, otherwise I did not find other points that caught my attention

  • 1

    Thank you so much for the @Rafaeltavares reply, I am deleting the old answer to avoid interpretation problems

2

As stated in documentation:

The guy never is a subtype and attributable to any other type. However, no type is subtype or attributable to it (except itself never). Up until any is not attributable to never.

It is basically a type that cannot happen. Its non-existence is a fact.

I am not going to go too far with the definition, as the documentation itself and the other answers here already provide this kind of information.


It is not valid to compare void with never, since it represents a value that exists (usually undefined) and it does not exist, so it does not represent any possible value. Note that void represents the absence of type (is the opposite of any), while never is the impossibility of having a value - applicable only for the type never.


It is rare to find any use case for never, but there are situations where it is especially useful. Generally, for narrow a set, as a union types. For example, we can create a type that removes numbers and strings:

type NonNumberString<T> = T extends string | number ? never : T;

type All = undefined | null | string | number | boolean | symbol;

// %inferred-type: boolean | symbol | null | undefined
type Filtered = NonNumberString<All>;

See on Typescript playground.

Basically, the guy NonNumberString uses a conditional type to check whether T is attributable to number or string. If yes, never will be returned. Otherwise, T will be returned. This removes, ie fine tune our type by deleting string or number.

In this specific case, the built-in type Exclude (see example here) comes to the same result. The intention here is to exemplify a case of use of narrowing types using the never.

Another interesting use case is to ensure, through the code flow analysis of Typescript, that a variable has the type never, that is, it cannot have value. This video explains this in more detail.

Browser other questions tagged

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