What is the difference between never and void in typescript?

前端 未结 8 2366
刺人心
刺人心 2020-12-15 15:04

I have read this, but it is unclear what would be the difference between \'never\' and \'void\' type?

相关标签:
8条回答
  • 2020-12-15 15:27

    In short:

    void returns void, never never returns.

    0 讨论(0)
  • 2020-12-15 15:28

    The type never means that nothing occurs. It is used when a type guard cannot occur, or in a situation where an exception is always thrown. There is a difference between void and never. A function that has the explicit return type of never won’t allow returning undefined, which is different from a void function which allows returning undefined.

    function functionThrow(): never {
    throw new Error("This function return never");
    

    }

    For example, in the code below, there is an enum with two items. TypeScript knows that only two cases are possible and the default (else) case cannot occur. This insight of TypeScript is perfect since the function return type only accepts string, and does not accept never. If in the future you add a new item from enum, (for example, a ChoiceC without adding a new case in the switch statement), then the code can call the unhandledChoice function which returns never.

     enum EnumWithChoices {
        ChoiceA,
        ChoiceB,
        ChoiceC,
    }
    
    function functionReturnStringFromEnum(c: EnumWithChoices): string {
        switch (c) {
            case EnumWithChoices.ChoiceA:
                return "A";
            case EnumWithChoices.ChoiceB:
                return "B";
            default:
                return unhandledChoiceFromEnum(c);
        }
    }
    
    function unhandledChoiceFromEnum(x: never): never {
        throw new Error("Choice not defined");
    }
    

    In the end, never indicates a state not meant to be. An exception is not expected behavior. An infinite loop in a function is not meant to be sustainable in a system, a condition that is never visited should not exist.

    0 讨论(0)
  • 2020-12-15 15:33

    Also, for more a theorical reason, with --strictNullChecks new flag, TypeScript needed a new bottom type (since null and undefined are no more). The type never is such a bottom type and make TypeScript's type system more consistent.

    0 讨论(0)
  • 2020-12-15 15:36

    Never is information that this particular part shouldn't be reachable. For example in this code,

    function do(): never {
        while (true) {}
    }
    

    you have an infinite loop and we don't want to iterate infinite loop. Simply as that.

    But a real question is how can it be useful for us? It might be helpful for instance while creating more advanced types to point what they are not

    for example, let's declare our own NonNullable type:

    type NonNullable<T> = T extends null | undefined ? never : T;
    

    Here we are checking if T is null or undefined. If it is then we are pointing that it should never happen. Then while using this type:

    let value: NonNullable<string>;
    value = "Test";
    value = null; // error
    

    Void is information that functions with this type don't return any value, but they are reachable and they can be used.

    0 讨论(0)
  • 2020-12-15 15:41

    In imperative languages, void can be thought of as a type containing a single value. Such languages do not provide a means to construct or consume this value, but a void function can be thought of as returning this trivial value.

    In contrast never is a type containing no values, which means that a function with this return type can never return normally at all. This means either throwing an exception or failing to terminate.

    0 讨论(0)
  • 2020-12-15 15:43

    To augment Lee's very good answer, another way to think of it is that in a correctly-typed program, a never value cannot be observed.

    In addition to functions which never return (or which always throw exceptions), you'll see the never type when a union type has been exhausted of all its possible constituents:

    // Example assumes --strictNullChecks
    function fn(x: number | string) {
      if (typeof x === 'number') {
        // x: number in this block
      } else if (typeof x === 'string') {
        // x: string in this block
      } else {
        // x: never in this block
        // this block does not run; the value of x cannot be observed
      }
    }
    
    0 讨论(0)
提交回复
热议问题