【问题标题】:Generic key name for object in callback function回调函数中对象的通用键名
【发布时间】:2020-09-30 13:53:16
【问题描述】:

有人能帮我理解为什么“失败”行会失败吗?以及如何在没有变通方法强制转换的情况下使其按预期工作?

function useObjectWithSingleNamedKey<Key extends string>(
  keyName: Key,
  value: string,
  fn: (obj: {[key in Key]: string}) => void)
{
  fn({ [keyName]: value }) // <-- Fails, but why?
  fn({ [keyName]: value } as { [key in Key]: string }) // <-- Unwanted workaround
}

useObjectWithSingleNamedKey('foobar', 'test', obj => {
  console.log(obj.foobar)  // <-- Should work and does
  console.log(obj.notHere) // <-- Should fail and does
});

Playground Link

我收到此错误:

类型参数 '{ [x: string]: string; }' 不可赋值
'{ [key in Key] 类型的参数:字符串; }'.(2345)

我想了解为什么目前失败,以及如何使其失败。

我怎样才能键入这个函数,以便它在类型方面仍然像现在一样在“外部”工作(即'foobar'keyName 形式传入obj.foober,而obj.notHere 或其他任何东西都是不是),但我可以在不使用 as 演员表的情况下调用 fn 函数。


注意: javascript code 工作正常,是 Typescript 类型检查失败,我不明白为什么会这样。

【问题讨论】:

  • 这是一个错误或设计限制;见microsoft/TypeScript#13948。您的类型断言(您称之为“强制转换”)是一种合理的解决方法。
  • @jcalz 啊...嗯,这很烦人,但我至少知道那里(目前)不是我真正正确执行此操作的方法。 IE。并不是我在这里误解了一些重要的东西,只是 Typescript 把事情搞砸了。

标签: typescript object typescript-generics


【解决方案1】:

它不起作用的原因是通用&lt;Key&gt; 在技术上可能比作为keyName 传递的文字字符串更广泛。

obj: {[key in Key]: string} 意味着obj 必须为可分配给Key 的每个可能的键都有一个值。您假设这只是一个键,但 typescript 并不确定。

这里作为一个例子来说明函数失败的地方。此函数调用完全有效,并且没有打字稿错误。失败在函数体内。

useObjectWithSingleNamedKey<'foo' | 'bar'>('foo', 'test', obj => {obj.bar});

如果我们说Key'foo' | 'bar'的并集,那么这里我们的对象obj的类型就假定为{foo: string; bar: string;}。当函数根据键和值参数创建对象时,{foo: string} 类型的对象将不足以满足预期的回调。

目前没有办法说Key 只能是单个文字字符串。

您可以使用现有的解决方法,并假设您不会像我的示例那样传递任何无意义的参数。

或者您可以重新考虑该功能。似乎您有一个回调,它作用于具有特定键的对象,并且您希望能够直接为特定值调用该回调。您需要分别传递键和值吗?你可以直接用 ({ [keyName]: value }) 调用你的回调吗?

您可以映射特定的回调以轻松接受值参数:

const barCallback = (obj: {bar: string}): string => obj.bar.toUpperCase();

const callBarCallback = (bar: string): string => barCallback({bar});

但是我们不能概括这种映射,因为我们不能确定对象只有一个属性。

【讨论】:

    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 2013-07-19
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    相关资源
    最近更新 更多