如何使用 Typescript 在其值中引用对象接口的键?

How do you reference an object interface's key in its value using Typescript?

我正在尝试创建一个对象接口(转换),它具有作为通用对象 (T) 属性的键,以便键可以映射到传递 属性 值的函数T 特定于传递的密钥。

interface Options<T> {
  headers: (keyof T)[]
  filename: string
  items: T[]
  transforms?: Partial<{
    [field in T as keyof T]: (item: T[field extends keyof T ? field : never]) => string
  }>
}

截至目前,项目始终解析为永不。我希望它能够解析为 T[field] 或者更确切地说 T[keyof T] 特定于它所附加的密钥。


编辑

这里有一个更好的例子来说明我试图完成的事情。我试图确保传递给变换对象中的函数的参数具有正确的类型 (T[keyof T]),这些函数具有作为 T 属性的键。在下面更正的示例中,color 应该是一个字符串,并且 isTasty 在作为参数传递给“transforms”时应该是一个布尔值。

interface Food {
  isTasty: boolean
  color: string
}

interface Options<T> {
  headers: (keyof T)[]
  filename: string
  items: T[]
  transforms?: Partial<{
    ?
  }>
}

function Foo<T>({headers, filename, items, transforms}: Options<T>){
  return 'bar'
}

Foo({
  headers: ['isTasty', 'color'],
  filename: 'test',
  items: [{color: 'red', isTasty: true}] as Food[],
  transforms: {
    color: (color) => '#' + color,
    isTasty: (isTasty) => isTasty ? 'Yes' : 'No'
  }
})

fixed and working example

您只希望 transforms 属性 成为 mapped type over the properties of T. Writing {[K in keyof T]: F<K>} will produce a new type with the same keys as T but whose properties are F<K> for each key type K. In your case, you want each property to be a function that accepts a value of the type corresponding to the property value of T at the key K. That is, a function that accepts a value of the indexed access type T[K]。像这样:

{ [K in keyof T]: (property: T[K]) => string }

注意如果要申请the Partial<T> utility type to it, you can write this more simply with the optional mapping modifier (?):

{ [K in keyof T]?: (property: T[K]) => string }

这为您提供了 Options<T> 的以下定义:

interface Options<T> {
  headers: (keyof T)[]
  filename: string
  items: T[]
  transforms?: {
    [K in keyof T]?: (property: T[K]) => string
  }
}

然后一切如你所愿:

function foo<T>(o: Options<T>) { }

foo({
  headers: ['isTasty', 'color'],
  filename: 'test',
  items: [{ color: 'red', isTasty: true }],
  transforms: {
    color: (color) => '#' + color,
    isTasty: (isTasty) => isTasty ? 'Yes' : 'No'
  }
})

Playground link to code