【问题标题】:How to properly type addField(obj, name, value) in typescript?如何在打字稿中正确键入 addField(obj, name, value)?
【发布时间】:2020-11-28 20:39:03
【问题描述】:

假设我有一个函数

function addField(obj, name, value) {
    return { ...obj, [name]: value }
}

如何在 Typescript 中输入?编辑:我遇到了返回类型的问题。我希望它是“原来的 T,但其中包含这个 [name] 属性”。

我希望这可以工作,但不幸的是它没有:

function addField<T, V>(obj: T, name: string, value: V): T & { `${name}`: V } {
    return { ...obj, [name]: value }
}

(它抱怨name 是一个值而不是一个类型)。所以,一种有效的破解方法是

// Hope that nameVal has only one key
function addField<T, V, N extends { [K: string]: V }>(
  obj: T,
  nameVal: N
): T & { [K in keyof N]: V } {
  return { ...obj, ...nameVal };
}

但这仍然不是我想要的 100%(因为它允许添加多个字段),而且它也不是很好。有没有更好的方法可以动态地将字段添加到对象并将其编码到类型 systen 中?

EDIT2:我想我可以使用this 来禁止具有多个键的对象,但我还是想保留原来的addField(obj, name, value)

【问题讨论】:

  • 你不需要返回类型,typescript可以推断出来。 Playground example
  • @MikeS。我的错,我在两个最上面的例子中有一个错字。我希望将字段名称作为参数动态提供。在这种情况下,TS 不会自动推断类型(或者说,不够精细)
  • 啊,那么this?唯一的问题是它允许重复的键,这可能不是你的意图
  • @MikeS。我想你不小心给我发了同一个文件。我只看到function addField&lt;T, K&gt;(obj: T, name : string, value : K) { ... }
  • 很奇怪,对我来说不一样。我只是把它贴在这里function addField&lt;T, K extends { [key : string]: unknown }&gt;(obj: T, value : K): T &amp; K { return { ...obj, ...value }; }你不需要第三个类型参数,因为打字稿应该能够从使用中推断出来。至于多键的事情,第二个参数将覆盖字段,这可能是也可能不是你的意图(虽然它不会重复)

标签: typescript types


【解决方案1】:

这是一个经常发生在我身上的正常问题。简而言之,TypeScript IntelliSense 并不完美,微软知道这一点。因此,TypeScript 可以输入 as unknown as [your type],但要小心,这不像在 CSS 中使用 !important 那样的好习惯。所以回到你可以简单使用的技巧的问题:

function addField<T, V, N extends string>(object: T, name: N, value: V) {
    return {
        ...object,
        [name]: value
    } as unknown as T & {
        [K in N]: V
    };
}

它工作正常: IntelliSense

【讨论】:

  • Díky — 呃,我是说,谢谢。没有我希望的那么好,但可能是我们目前能做的最好的。
  • 只有一件事——你能解释一下为什么unkown在这里是必要的吗? (主要是为将来会读到这篇文章的人准备的)
  • 因此是兼容的类型(如父类和派生类)和不兼容的类型(如数字和字符串)。您只能将as 与两种兼容类型一起使用。 (在一个例子中,它们是不兼容的)。 anyunknown 是通配符,兼容所有类型。请参阅typescriptlang.org/docs/handbook/type-compatibility.html 了解更多信息。
猜你喜欢
  • 2020-06-27
  • 1970-01-01
  • 2021-05-04
  • 2021-06-22
  • 2022-11-18
  • 2020-04-22
  • 2021-12-17
  • 2020-08-02
  • 2017-03-14
相关资源
最近更新 更多