TypeScript、详尽性检查无法正常工作

标签 typescript

假设我们正在为 Post 编写数据库模型,并且由于数据库将所有内容存储为字符串,我们需要编写 parse 函数,该函数将获取原始数据库对象并将其转换为正确的 Post 接口(interface)。

重现设置noImplicitReturns: true

interface Post {
  id:   number
  text: string
}

function parse<K extends keyof Post>(k: K, v: any): Post[K] {
  switch(k) {
    case 'id':   return parseInt(v)
    case 'text': return v.toString()
  }
}

该代码中有两个错误。首先 - 它不会编译,似乎 TypeScript 没有意识到我们的代码是正确的,并要求将 default 语句添加到 switch 中。

第二个错误 - 它不会检测到您正在检查错误的值。下面的错误代码将编译没有错误

function parse<K extends keyof Post>(k: K, v: any): Post[K] {
  switch(k) {
    case 'id':   return parseInt(v)
    case 'text': return v.toString()
    case 'some': return v.toString() // <= error, no `some` key
    default: return ''               // <= this line is not needed
  }
}

甚至还有第三个错误,TypeScript 会允许返回错误的键值,这个错误的代码会编译

function parse<K extends keyof Post>(k: K, v: any): Post[K] {
  switch(k) {
    case 'id':   return parseInt(v)
    case 'text': return 2 // <= error, it should be string, not number
    default: return ''
  }
}

这些 TypeScript 限制还是我搞错了?

最佳答案

首先,K扩展keyof Post并不意味着Kkeyof Post,所以不要使用泛型类型K,您必须使用keyof Post来限制K的潜在值。

其次,如果您在 tsconfig.json 中设置 "switch-default": true, ,则会强制使用默认选项。因此将其设置为 false 那么问题就会消失。

第三,Post[K] 甚至 Post[keyof Post] 将返回 Post 属性的所有可能类型,因此 number 是可能的。 Typescript 不会强制 Post[K] 为其 K 属性的类型,除非您指出 K 是哪个。否则,您必须定义映射类型,例如 type A = ['id', numer] | [text', string] 并将 Post 定义为 [A[0]]: A[1]

希望这有帮助

关于TypeScript、详尽性检查无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54821093/

相关文章:

javascript - 动态创建的选择不绑定(bind)到它们的可观察值?

javascript - Angular 2 自定义管道实现

typescript - 当参数是函数时不推断通用类型参数

javascript - 如何从 typescript 调用 JavaScript 包含中的方法?

typescript - 如何覆盖 TypeScript 中的类型属性

typescript - 在nestjs中具有嵌套对象数组的类验证器

javascript - 如何使用带有 expo 的 React-Navigation 正确键入作为 Prop 传递的导航

reactjs - 如何在 react-redux 中正确键入映射到 Prop 的 Action 创建者

TypeScript:跨多个文件引用接口(interface)时找不到名称错误

javascript - 什么时候应该在 JavaScript/TypeScript 中使用 `export default`?