首页 > 解决方案 > 如何推断对象属性的类型

问题描述

我有以下代码,我想推断对象属性的类型。如您所见,v在我的示例中推断的类型是{}. 我该如何编写myValue以便C在编译时由 Typescript 推断?


const myValue = <T1, T2>(prop: string, obj: T1): T2 => {
  return obj[prop]
}

interface C {
  readonly c: string
}

interface TestInt {
  readonly a: string
  readonly b: number
  readonly c: C
}

const test: TestInt = {
  a: 'a',
  b: 1,
  c: {
    c: 'c',
  },
}

const v = myValue('c', test) // const v: {}

标签: typescripttype-inference

解决方案


当您拥有要推断的类型的实际值时,类型参数推断效果最佳。拥有T2函数返回值的类型很可能是个问题。除非您在期望返回值是 typemyValue()的上下文中调用,否则编译器会推断它的希望很小...从返回值推断类型参数称为上下文类型,不幸的是,在没有上下文类型。它可以是任何东西。 CCconst v = myValue(...)v

那么你实际上有哪些类型的值?由于您myValue()使用propobj参数调用,因此首先要尝试的是给出obj一个泛型类型T,并给出prop另一个泛型类型,如K.... 和 inferTKfrom objand prop

请注意,您打算 thatprop应该是 的键之一,因此您对 的类型obj有一个自然约束K,即它应该扩展keyof T

最后,您的函数的返回类型可以从其他类型派生。它应该是T其键为的属性的类型K。这可以表示为T[K]查找类型)。

这是函数的最终版本:

const myValue = <T, K extends keyof T>(prop: K, obj: T): T[K] => {
    return obj[prop];
}

请注意该函数与文档中getProperty()提到的函数和查找类型之间的相似性。唯一的区别是参数的顺序(嗯,返回类型是推断而不是注释的事实......以及函数名称,我猜)。keyof

当我们使用 的定义时myValue(),我们得到:

interface C {
    readonly c: string
}

interface TestInt {
    readonly a: string
    readonly b: number
    readonly c: C
}

const test: TestInt = {
    a: 'a',
    b: 1,
    c: {
        c: 'c',
    },
}

const v = myValue('c', test) // const v: C

如你所愿。

希望有帮助;祝你好运!


推荐阅读