如果变量不是 never 类型,如何创建编译器错误?

问题描述 投票:0回答:1

假设我有一个条件列表,我想处理

type
的每个可能值。如果我将来添加了一个新的
type
并且忘记处理它,我想要一个错误 - 至少是一个运行时错误,但理想情况下是一个编译器错误,这样我就可以在部署之前发现我的错误。

如何断言变量的类型为

never

type Job = { type: 'add'; payload: any } | { type: 'send'; payload: any }

const handleJob = (job: Job) => {
  const add = (job: Job) => {
    console.log(job)
  }
  const send = (job: Job) => {
    console.log(job)
  }

  if (job.type === 'add') {
    add(job)
  } else if (job.type === 'send') {
    send(job)
  } else {
    // `job` is actually type `never` here,
    // this error won't ever be thrown unless additional strings are added to the `Job.type` schema.
    throw new Error(`Unhandled job.type "${(job as Job).type}".`)
  }
}
typescript typescript-never
1个回答
0
投票

您可以引入一个

never
返回函数,它只接受
never
类型
的参数,这意味着编译器只有在实际上不希望调用该函数时才会感到高兴。这个函数通常被称为
assertNever()
。这是一种写法:

function assertNever(x: never, msg?: string): never {
  throw new Error(msg ?? "unexpected value " + String(x));
}

如果它确实被调用,那么您将收到运行时错误。现在以下内容按预期编译:

if (job.type === 'add') {
  add(job)
} else if (job.type === 'send') {
  send(job)
} else {
  assertNever(job, // <-- okay    
    `Unhandled job.type "${(job as Job).type}".`
  );
}

但是如果我们添加新的工作类型:

type Job =
  { type: 'add'; payload: any } |
  { type: 'send'; payload: any } | 
  { type: 'explode' }; // add this

现在失败了,也正如预期的那样:

if (job.type === 'add') {
  add(job)
} else if (job.type === 'send') {
  send(job)
} else {
  assertNever(job, // error!   
    // -----> ~~~
    // Argument of type '{ type: "explode"; }' is 
    // not assignable to parameter of type 'never'.
    `Unhandled job.type "${(job as Job).type}".`
  );
}

编译器错误警告您尚未处理新类型,这应该会提示您添加另一个

if
/
else
语句

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.