在打字稿中使用never关键字

Neo*_*Ash 20 typescript

TS文档说," 从不类型表示永远不会发生的值的类型.变量也会获得从未被任何类型的守卫缩小的类型."

我不明白它的用法,任何人都可以用一些例子给我答案.

Wil*_*een 14

the never type represents the type of values that never occur:

The Typescript compiler assigns types to all your variables/properties. These types can be either the typescript defined types like number and string, or user defined types made with the interface and type keyword.

It is useful to think of these types as sets. In other words a type itself is a collection of possible things which your variables/properties can be at that time. For example:

// the variable five can be one thing which is a number
const foo = 5; // type = number; 

// bar can be two things
type twoPrimitives = string | number;
let bar: twoPrimitives = 4; 
Run Code Online (Sandbox Code Playgroud)
  • We see foo has a set size of 1 >> {number}
  • We see bar has a set size of 2 >> {number, string}

Now with our set definition in mind we can define the never type easy:

the never type represents the empty type set >> {}. i.e. a set with 0 items in it.

For example:

// Normally a function which do not have a return value returns undefined implicitly
// However this function throws before ever reaching the end. 
// Therefore the return type will be never
function foo() :never {
   throw new Error("Error");
}

// thisMakesNoSense will be type never, a value can never be number and string at the same time
type thisMakesNoSense = number & string; 
Run Code Online (Sandbox Code Playgroud)

Variables also acquire the type never when narrowed by any type guards that can never be true.

TS can check narrow types if they are explicitly checked in if statements. This is called type guards. In other words a type guard is some expression that performs a runtime check that guarantees the type in a certain scope. For example:

// The compiler actually screens these if statements and can infer that in the third
// else statement there are no more types left for value to take on and thus the type 
// become never. Another way to think about this is that in the first if statement the
// set of possible types shrinks from string | number to number only.
// Then in the seconds if statement it shrinks from number to never
function typeGuards(
    value: string | number
) {
    if (typeof value === "string") {
        value; // Type string
    } else if (typeof value === "number") {
        value; // Type number
    } else {
        value; // Type never
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 迄今为止对“从不”类型的最好解释,谢谢。 (4认同)

Krz*_*bek 13

  1. 永不类型代表永不出现的值的类型。

可能是永不返回的函数的返回类型:

const reportError = function () {
    throw Error('my error');
}

const loop = function () {
    while(true) {}
}
Run Code Online (Sandbox Code Playgroud)

在这里,reportErrorlooptype均为() => never

  1. 变量也永远不会被任何永远不可能为真的类型防护所缩小,而获得类型

使用或这样的运算符typeof,我们可以缩小变量类型的范围。我们可以缩小类型的范围,以确保在某些地方不会发生此变量。instanceofin

function format(value: string | number) {
    if (typeof value === 'string') {
        return value.trim();
    } else {
        return value.toFixed(2); // we're sure it's number
    }

    // not a string or number
    // "value" can't occur here, so it's type "never"
}
Run Code Online (Sandbox Code Playgroud)
  1. 常见用例

除了更好的类型安全性(如上述情况)外,never类型还有另一个用例-条件类型。使用never类型,我们可以排除一些不需要的类型:

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

type A = NonNullable<boolean>;            // boolean
type B = NonNullable<number | null>;      // number
Run Code Online (Sandbox Code Playgroud)

  • 您能详细解释一下最后一个案例或提供一个例子吗? (2认同)
  • @Tooster这是因为“分布式条件类型”:https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types (2认同)

Mar*_*ton 6

从不存在的Typescript文档中有多个示例:

// Function returning never must have unreachable end point
function error(message: string): never {
    throw new Error(message);
}

// Inferred return type is never
function fail() {
    return error("Something failed");
}

// Function returning never must have unreachable end point
function infiniteLoop(): never {
    while (true) {
    }
}
Run Code Online (Sandbox Code Playgroud)


Apu*_*hak 5

友情链接,我从研究: https://www.typescriptlang.org/docs/handbook/basic-types.html https://basarat.gitbooks.io/typescript/docs/types/never.html https://开头理论家。 io/lessons/typescript-use-the-never-type-to-avoid-code-with-dead-ends-using-typescript https://blog.mariusschulz.com/2016/11/18/typescript-2-0 -从不类型

可以总结为 never 类型用于以下情况:

  1. 函数永远不会返回(例如,如果函数体具有while(true){}

    //Type () => never
    
    const sing = function() {
    while (true) {
        console.log("Never gonna give you up");
        console.log("Never gonna let you down");
        console.log("Never gonna run around and desert you");
        console.log("Never gonna make you cry");
        console.log("Never gonna say goodbye");
        console.log("Never gonna tell a lie and hurt you");
    }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  2. 函数总是抛出(例如,在函数foo(){throw new Error('Not Implemented')} 中,foo 的返回类型永远不会)

    // Type (message: string) => never
    const failwith = (message: string) => {
        throw new Error(message);
    };
    
    Run Code Online (Sandbox Code Playgroud)

用例:详尽检查

function foo(x: string | number): boolean {
  if (typeof x === "string") {
    return true;
  } else if (typeof x === "number") {
    return false;
  }

  // Without a never type we would error :
  // - Not all code paths return a value (strict null checks)
  // - Or Unreachable code detected
  // But because TypeScript understands that `fail` function returns `never`
  // It can allow you to call it as you might be using it for runtime safety / exhaustive checks.
  return fail("Unexhaustive!");
}

function fail(message: string): never { throw new Error(message); }
Run Code Online (Sandbox Code Playgroud)

  • 没想到会得到如此答案哈哈哈哈。感谢那 (7认同)

day*_*ily 5

never是具有 0 值的类型。

正如和boolean中的任何一个,这意味着有且只有 2 种构造类型值的方法,在 TypeScript 中构造类型值的方法正好有 0 种。truefalsebooleannever

但你可能会问,“never那有什么用呢?”

在 TypeScript 中,值是由表达式生成的。表达式也有类型,它们与它们求值的类型相同。parseInt("123")是 类型number,而[1, 2, 3]是 类型number[]。但并非所有表达式都可以计算为值。考虑:

function f() {
  return f()
}
Run Code Online (Sandbox Code Playgroud)

一个表情f()不会让你一事无成。f()返回,不断f()返回f(),并且此递归继续,直到达到最大递归限制并且程序崩溃。

所以f()无论如何都不会评估任何值。但这个表达式仍然需要有一个类型;哪个?

答案是任何类型都可以。毕竟它不会给我们机会使用它的返回值(因为它没有返回值;也因为它会无限期地运行)所以我们可以写

function f(): number {
  return f()
}
Run Code Online (Sandbox Code Playgroud)

这就是f()类型number;甚至写

function f<T>(): T {
  return f()
}
Run Code Online (Sandbox Code Playgroud)

但通常,我们会写never

function f(): never {
  return f()
}
Run Code Online (Sandbox Code Playgroud)

所以never在这里扮演了一个新的角色;它是一种没有值的类型,因此它标志着该表达式是特殊的,它会导致程序执行除产生值之外的其他操作,例如无限期地继续运行。

更常见的是,您会看到never肯定会引发错误或导致程序终止的代码:

function throwSomeError(): never {
  throw new Error()
}

function bye(): never {
  process.exit(0)
}
Run Code Online (Sandbox Code Playgroud)

这些函数也不会返回任何值,因此我们可以为它们的“返回类型”选择任何实际上不存在的类型,但我们通常用来never表示这些函数是非常特殊的函数。


Seb*_*ald 4

一个例子是如果您抛出一个错误。例如

function throwError () {
  throw new Error('whoops');
}
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到更多信息:https://basarat.gitbooks.io/typescript/content/docs/types/never.html

  • `throw` 是一个保留关键字,不能将其用作函数声明的名称:`Uncaught SyntaxError: Unexpected token throw` (2认同)