【问题标题】:Type inference with in operator使用 in 运算符进行类型推断
【发布时间】:2018-01-26 02:02:11
【问题描述】:

Typescript 不允许使用 in-operator 推断对象的类型。

例如,

function getKey<T extends object, U extends string> (obj: T, key: U) {
    if (key in obj) {
        return obj[key] // Type 'U' cannot be used to index type 'T'.
    }
}

Typescript 应该识别出 Ukeyof T,所以我可以将它用作键。

如何在不使用 any 的情况下解决这个问题?

【问题讨论】:

  • 您希望以U 传递什么类型?如果它是string 的有效子类型,您可以省略它,只使用:getKey&lt;T extends object&gt; (obj: T, key: string) {。如果您只想使用已知的有效密钥,请使用 Titian 的答案。
  • Fenton,我想允许任何键。我使用 in-operator 作为标志。
  • 你能分享一个 TypeScript 阻止这种情况的最小工作示例吗?我能想到一个修复方法,但想先测试一下。

标签: typescript casting


【解决方案1】:

您需要将U 声明为扩展keyof T,以便在没有string 索引器的情况下使用它来索引对象。

function getKey<T extends object, U extends keyof T> (obj: T, key: U) {
    if (key in obj) {
        return obj[key] // Now works!
    }
}

由于PR 用于in 类型保护表明保护影响T 的类型而不是键的类型,因此您仍然需要明确告诉编译器U 扩展keyof T

如果您想将U 保留为string(我鼓励您考虑是否真的需要它作为类型参数并且您不能只使用string 作为参数)您可以函数的多个签名:

// The visible signatures of the function 
// The first one takes keyof T and infers return type based on it
function getKey<T extends object, U extends keyof T> (obj: T, key: U) : T[U]
// The second one takes string and will return any 
function getKey<T extends object> (obj: T, key: string) : any
// The implementation signature allows indexing, this will not be public.
function getKey(obj: { [index: string]: any }, key: string) {
    if (key in obj) {
        return obj[key] // Can now index T
    }
}

let r = getKey({ type: "test"}, "type"); // r is infered to `test`
let r2 = getKey({ type: "test"}, "notAProp"); // r is infered to any

【讨论】:

  • 我不想将 key 限制为 keyof T,这本身就已经使操作员内无用。我想允许任何字符串类型。
  • 如果属性是可选的,它不会完全没用,但我明白你的意思。我将添加一个替代方案
  • 谢谢。有没有办法推断返回类型?
  • @zaclummys 添加了一个重载,在编译时已知的情况下根据属性名称键入结果
猜你喜欢
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 2021-03-05
  • 2019-12-26
相关资源
最近更新 更多