首页 > 解决方案 > 打字稿泛型:将键作为函数 arg 传递,将另一个 arg 推断为值

问题描述

我想要的是

我有一个对象和一个“消费者”函数,它接受一个键和处理程序函数,然后将该键的值传递给处理程序。

我希望 Typescript 在运行时给定任意键来推断处理函数的正确类型。

我希望它使用密钥作为正确处理程序的“选择器”,并在使用该处理程序时具有类型安全性。我知道我可以在给定密钥的处理程序中手动键入参数,但我希望自动推断它以具有适当的类型安全性。例如,如果我更改键而不是处理程序的实现,则中断。

我试过的

打字稿游乐场链接

type Things<T> = {
  [K in keyof T]: T[K]
}

type ThingConsumer<T, K extends keyof T> = (
  forThingOfType: K,
  handler: (value: T[K]) => void,
) => void

function createThings<T>(things: Things<T>): Things<T> {
  return things
}

function createThingConsumer<T, K extends keyof T>(
  things: Things<T>,
): ThingConsumer<T, K> {
  return (forThingOfType, handler) => handler(things[forThingOfType])
}

const things = createThings({
  a: { foo: 1, bar: 2 },
  b: { baz: 3 },
})

const thingConsumer= createThingConsumer(things)

thingConsumer('a', (value) => {
  console.log(value.foo + 1) // <-- error: Object may be 'undefined'
})

什么不起作用

看来 Typescript 无法从传递的密钥中value正确推断出具体类型, .{ foo: number, bar: number }'a'

相反,它推断value为 的所有可能值的联合类型things,即

{ foo: number, bar: number } | { baz: number }

然后尝试使用时的错误信息value.foo是非常意外的。它说“对象”可能是未定义的。如果有的话,我会期望它抱怨foo可能是未定义的,考虑到联合类型推断,但不是它value本身可能是未定义的。

我正在尝试做的事情可能吗?

感觉应该是这样 - 特别是我真的认为T[K]语法说“对于一个给定K的对象的具体键,解析相应值的类型”。但也许它没有那么强大,而是说'对于任何键,解决任何值'?

标签: typescript

解决方案



推荐阅读