typescript - 为什么 Typescript 将我的 keyof 类型强制为 never 类型,我该如何解决?
问题描述
抱歉,如果这是一个骗局,我是 TypeScript 的新手,我无法弄清楚看起来相似的问题是否相关,因为他们中的很多人都在做非常复杂的事情。无论如何,问题是,我有一个相对简单的设置,TS 正在窒息,因为它强制类型never
,我真的不明白它为什么这样做。这是设置:
interface BigObject {
foo: {
a?: string
b?: string
}
bar: {
c?: string
d?: string
}
}
const instance: BigObject = {
foo: {
a: "a",
b: "b",
},
bar: {
c: "c",
d: "d",
}
}
function metafunction(bigObjProp: keyof BigObject) {
type LittleObject = BigObject[typeof bigObjProp]
// IDE hints show this ^^ as being correct, i.e. either of the two "sub interfaces"
return function (littleObjProp: keyof LittleObject) { // <== littleObjProp is resolving to never
return function (bigObject: BigObject) {
const littleObject = bigObject[bigObjProp]
return littleObject ? littleObject[littleObjProp] : "fallback value"
}
}
}
const firstClosure = metafunction("foo")
const secondClosure = firstClosure("a") // <== Argument of type "a" is not assignable to type "never"
const value = secondClosure(instance)
我的期望是值value
将是“a”。
我不明白为什么littleObjProp
解析为never
. 我的假设是,因为LittleObject
是根据传入的参数类型构建的metafunction
,所以 TS 会选择用于任何给定调用的“子接口”。因此,例如,当我调用 时metafunction("foo")
,TS 会设置LittleObject
为{ a?: string; b?: string }
,因此,当我调用 时firstClosure("a")
,它会说:“是的,'a' 确实是 LittleObject 的有效键,继续”。然而,它不能这样做,因为它总是认为这keyof LittleObject
意味着never
.
有人可以帮助我理解 1)为什么要这样做和 2)如何完成我想要做的事情?我意识到这是一个奇怪的设置,但我正在处理一些奇怪的 React 库,而这正是我目前所处的位置。请假设我必须保持与示例中所示的返回函数的函数相同的整体结构。另外,如果您可以使答案尽可能简单,我将不胜感激,因为我对 TS 有点陌生。提前致谢!
解决方案
使metafunction
通用。
正如你上面所说的,没有泛型类型。为了安全起见firstClosure
,只需要一个有共同点的密钥foo
,bar
但它们没有共同的密钥,所以这never
是唯一可能的参数。如果你要给他们一个共同的钥匙,firstClosure
就会被打字接受。
interface BigObject {
foo: {
a?: string
b?: string
f?: string // Added
}
bar: {
c?: string
d?: string
f?: string // Added
}
}
const instance: BigObject = {
foo: {
a: "a",
b: "b",
f: "f",
},
bar: {
c: "c",
d: "d",
f: "f",
}
}
const secondClosure = firstClosure("f") // "f" is the only valid value
通过添加泛型,您可以说服 Typescript 将类型信息保留为metafunction
and firstClosure
each 的属性,从而为您的闭包提供您正在寻找的类型。
function metafunction<T extends keyof BigObject>(bigObjProp: T) {
type LittleObject = BigObject[T]
return function (littleObjProp: keyof LittleObject) {
return function (bigObject: BigObject) {
const littleObject = bigObject[bigObjProp]
return littleObject[littleObjProp] ?? "fallback value"
}
}
}
推荐阅读
- java - java.nio.file.NoSuchFileException 在java中删除文件时
- python - 如何在 Glue 作业脚本中设置模块
- python - 遍历css文件中的url并使用python替换文本
- javascript - 从 gulp 编译中排除文件
- continuous-integration - 避免在完成发布时为开发分支构建 Gitlab-CI (git-flow)
- c# - ModelStateDictionary - 识别不应返回给调用者的错误
- python-3.x - 如何获取 django 脚本的正确路径
- angular - Angular:部署期间的动态配置
- vb.net - VB.net 排序面板控件
- c++ - 如何对 sparxe 体素八叉树 (SVO) 进行三角测量