使用strictNullChecks的TypeScript控制流分析不会缩小联合类型

时间:2016-09-30 09:27:57

标签: typescript

我有以下代码https://hamednourhani.gitbooks.io/typescript-book/

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

//Type of function: function area1(s: Square | Rectangle | Circle): number | undefined
function area1(s: Shape) {
    if (s.kind === "square") {
        return s.size * s.size;
    }
    else if (s.kind === "rectangle") {
        return s.width * s.height;
    }
    else if (s.kind === "circle") {
        return Math.PI * s.radius * s.radius;
    }
    else {
        //Type 'Square | Rectangle' is not assignable to type 'never'.
        const _exhaustiveCheck: never = s;
    }
}

//Function lacks ending return statement and return type does not include 'undefined'.
function area2(s: Shape): number {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
        default: const _exhaustiveCheck: never = s; //Type of s is 'never'
    }
}

问题(--strictNullChecks):

  • 为什么表达式s中的2个函数_exhaustiveCheck: never = s 有不同的类型?在这两种情况下,我都希望snever
  • 为什么area2函数想要返回类型number | undefined?在我看来,undefined永远不会发生在这里。我错了吗?

1 个答案:

答案 0 :(得分:1)

  

我有以下代码https://hamednourhani.gitbooks.io/typescript-book/

那本书的网址有误。原来的是:http://basarat.gitbooks.io/typescript/。由于它的免费和开源意味着人们可以自由地创建重复项。没有多烦我(似乎是无心的,我假设没有恶意),但我想提到最新的版本链接。现在回答你的问题

  

为什么在表达式_exhaustiveCheck中的2个函数中:never = s有不同的类型?我希望在两种情况下都不会。

您发布的代码也不是本书相关部分中的代码https://basarat.gitbooks.io/typescript/content/docs/types/discriminated-unions.html假设您修改了它:)

很好。当我运行你的样本时,我得到两个版本的never。正如您所看到的,s在两种情况下都属于never类型,并且没有错误。评论错了:

enter image description here

  

为什么area2函数想要返回类型号|未定义?在我看来,undefined永远不会发生在这里。我错了吗?

要明确两个函数都希望类型为number | undefined。这只是因为TypeScript已经发现有些代码在某个区域执行但没有返回。它没有发现该地区是never地区。但是,您可以轻松地帮助它,只需返回never即可。固定代码:

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

// Type of function: function area1(s: Square | Rectangle | Circle): number
function area1(s: Shape) {
    if (s.kind === "square") {
        return s.size * s.size;
    }
    else if (s.kind === "rectangle") {
        return s.width * s.height;
    }
    else if (s.kind === "circle") {
        return Math.PI * s.radius * s.radius;
    }
    else {
      // Type of s is never
      const _exhaustiveCheck: never = s;
      return _exhaustiveCheck;
    }
}

// No Error 
function area2(s: Shape): number {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
        default:
          const _exhaustiveCheck: never = s; // Type of s is 'never'
          return _exhaustiveCheck;
    }
}

PS:我已经使用strictNullChecks更新了这本书:https://github.com/basarat/typescript-book/blob/master/docs/types/discriminated-unions.md#strictnullchecks