假设我有一个条件列表,我想处理每个可能的值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}".`)
  }
}

推荐答案

你可以引入一个只接受参数the never typenever-returning function,这意味着编译器只有在它实际上不期望调用函数时才会感到高兴.这个函数通常被称为assertNever().这里有一种方式来写它:

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

如果它does被调用,那么你会得到一个运行时错误.现在,以下代码按预期编译:

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

fails,也如预期:

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 statement个.

Playground link to code

Typescript相关问答推荐

具有映射返回类型的通用设置实用程序

TypScript手册中的never[]参数类型是什么意思?

TypeScript泛型参数抛出错误—?&#"' 39;预期"

使用`renderToPipeableStream`时如何正确恢复服务器端Apollo缓存?

在嵌套属性中使用Required

对扩展某种类型的属性子集进行操作的函数

在分配给类型的只读变量中维护const的类型

如何 bootstrap TS编译器为类型化属性`T`推断正确的类型?

`fetcher.load`是否等同于Get Submit?

TypeScrip泛型类未提供预期的类型错误

如何以Angular 导入其他组件S配置文件

不带其他属性的精确函数返回类型

声明遵循映射类型的接口

打印脚本中正则函数和函数表达式的不同类型缩小行为

有没有什么方法可以使用ProvideState()提供多个削减器作为根减减器

基于属性值的条件类型

Vite+Chrome扩展 list v3-;不能在模块外使用import语句;对于inpage脚本

为什么TS条件返回要求不明确的强制转换而不是精确的强制转换?

显式推断对象为只读

redux-toolkit、createAsyncThunk 错误