用户定义的守卫不再工作了?

User-defined guards not working anymore?

以下代码在打字稿 2.0 之前有效:

class Aluno{
  escola: string;
  constructor(public nome: string){
    this.escola = "";
  }
}
class Pessoa{
  morada: string;
  constructor(public nome: string){
    this.morada = "";
  }
}
function ePessoa(p: Pessoa | Aluno): p is Pessoa{
  return (<Pessoa>p).morada !== undefined;
}
function eAluno(p: Pessoa | Aluno): p is Aluno{
  return (<Aluno>p).escola !== undefined; 
}
let a: Pessoa | Aluno = new Pessoa("Luis");
console.log( a.nome ); //ok
a = new Aluno("Rui");
console.log( a.nome ); //ok
//a.escola = "teste";//erro
if(eAluno(a)){
  console.log("Aluno da escola:" + a.escola);
}
else{
  console.log("Pessoa residente em: " + a.morada); //morada does not exist
}

编译器似乎没有将 else 分支中的 a 视为 Pessoa。我错过了什么吗?

准确的错误是:

Property 'morada' does not exist on type 'never'

你得到它的原因是因为编译器足够聪明,可以看到永远不会访问 else 部分。

你在做:

let a: Pessoa | Aluno = new Pessoa("Luis");
...
a = new Aluno("Rui");

所以当你到达 if 时肯定会 Aluno,它永远不会 Pessoa

这里有更多关于 never type 的信息。


编辑

重要的是编译器会限制开发人员做错事。
许多 javascript 开发人员会争辩说 typescript 是多余的,不需要类型,但你仍然在这里使用它。

您收到的错误很重要,因为 Unreachable code 错误:

function fn(): boolean {
    return false;

    let a = 3; // Error: Unreachable code detected
}

(code in playground)

为什么您希望拥有永远不会执行的代码部分?
这就像没有它们加上使用代码和更改维护它们以及在处理代码时考虑它们的麻烦。


第二次编辑

编译器不会对整个流程进行检查,因此只有当编译器在当前范围内检测到它时,您才会收到错误消息。
Unreachable code 错误相同:

function fn(): boolean {
    throw new Error("error");
}

let a = fn();
if (a) { // no error
    console.log("all good");
}

但是:

let a = fn();
throw new Error("error");
if (a) { // Error: Unreachable code detected
    console.log("all good");
}