[英]Why is Typescript coercing my keyof type to a never type and how do I fix it?
对不起,如果这是一个骗局,我是 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 的value
将是“a”。
我不明白为什么littleObjProp
解析为never
。 我的假设是,由于LittleObject
是从传递给参数的类型内置metafunction
,TS会选择使用任何给定调用其“子接口”。 因此,例如,当我调用metafunction("foo")
,TS 会将LittleObject
设置为{ a?: string; b?: string }
{ a?: string; b?: string }
因此,当我调用firstClosure("a")
,它会说,“啊,是的,'a' 确实是 LittleObject 的有效键,继续”。 然而,它不能这样做,因为它总是认为keyof LittleObject
意味着never
。
有人可以帮助我理解 1) 为什么这样做和 2) 如何完成我正在尝试做的事情? 我意识到这是一个奇怪的设置,但我正在处理一些奇怪的 React 库,而这正是我目前所处的位置。 请假设我必须保持一个函数的整体结构,该函数返回一个返回一个函数的函数,如示例中所示。 另外,如果您能尽可能简单地回答我的问题,我将不胜感激,因为我对 TS 有点陌生。 提前致谢!
使metafunction
通用。
正如上面所说,没有泛型类型。 为了安全起见, firstClosure
只会采用foo
和bar
共有的键,但它们没有共同的键,所以never
是唯一可能的参数。 如果您要给它们一个共同的键, firstClosure
键入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
和firstClosure
每个的属性,这为您的闭包提供您正在寻找的类型。
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"
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.