【问题标题】:How do you dynamically update a key-value pair on a typed object in TypeScript如何在 TypeScript 中动态更新类型化对象的键值对
【发布时间】:2020-07-20 02:25:48
【问题描述】:

我正在尝试创建一个函数,该函数接受一个键和一个值并更新类型化对象上的相应键值对。这是我所追求的基本示例。

Link to code sandbox with below code

type x = {
    prop : number,
    other : string
}

let dataToUpdate : x = {
    prop: 1,
    other: "string"
}

function updateKey(key : string, value : number | string) {
    dataToUpdate[key] = value;
}

我在上面的实现中遇到了这个错误。

元素隐式具有'any' 类型,因为'string' 类型的表达式不能用于索引'x' 类型。 在 'x' 类型上找不到带有 'string' 类型参数的索引签名。(7053)

更新 我被介绍了XY Problem 的想法。下面是我所追求的实际实现。我正在尝试在 React 中创建一个上下文,该上下文返回一个函数,该函数允许您仅更新存储在上下文中的对象中的特定属性

export function StoreProvider(props: any) {
    const [storeData, setStoreData] = useState<StoreData>(initProviderData);

    function setStoreKeyValue(keyToUpdate: keyof StoreData[], valueToSet: boolean | string | number | null){
        let newStoreData = {...storeData);
        const isStoreData = Object.keys(initProviderData).filter((key) => { key == keyToUpdate }).length > 1;

        if (isStoreData && newStoreData) {
            newStoreData[keyToUpdate] = valueToSet;
            setStoreData(newStoreData)
        }
    }

    return (
        <StoreContext.Provider value={{ "storeData": storeData, "setStoreData": setStoreData }}>
            {props.children}
        </StoreContext.Provider>
    )
}

【问题讨论】:

标签: reactjs typescript


【解决方案1】:

TLDR;

updateKey<K extends keyof X>(key: K, value: X[K]) {
  dataToUpdate[key] = value; 
}

详情

给定

type X = {
  prop: number;
  other: string;
};

const dataToUpdate: X = {
    prop: 1,
    other: "string"
};

TypeScript 不允许我们通过任意属性键类型(例如 string)访问具有已知属性集的类型良好的对象的属性,例如您的 dataToUpdate

由于语言知道dataToUpdate的唯一键是"prop""other",因此必须对更新函数的key参数进行相应的限制。

虽然我们可以在参数列表key: "prop" | "other" 中显式写出联合类型,但这种模式对于 JavaScript 来说是如此基础,以至于 TypeScript 提供了 keyof 类型运算符,它生成给定的所有属性键的联合类型类型,允许我们写

updateKey(key: keyof X, value: string | number) {
  dataToUpdate[key] = value; 
}

但是,我们还没有完成,因为语言需要确保value 参数的类型对应于指定的key 的属性类型,并且碰巧"prop" 必须是@ 987654334@ 和 "other" 必须是 string

为了描述这一点,我们将声明调整如下

updateKey<K extends keyof X>(key: K, value: X[K])

我们所做的是将两个参数的类型关联起来,使得value 的类型与key 指定的属性类型相匹配,无论何时调用该函数。

【讨论】:

    【解决方案2】:

    @Aluan 给出的答案是绝对正确的,但还有另一种方法。只需将动态键添加到您的类型,如下所示:

    type x = {
        prop : number,
        other : string,
        [key: string]: string | number;
    }
    

    【讨论】:

    • 虽然这在技术上解决了类型 x 的情况,但当您开始使用更复杂的类型时,它就没有那么可扩展了。在我的例子中,我有一个类型有几个键,它们的类型都不同,所以在这种情况下,你最终可以基本上允许隐式类型 any。 @Aluan Haddad 的回复允许使用任意数量和类型的键,而不会丢失对参数的严格输入
    • 我同意你,肖恩。这甚至只适用于必填字段。
    猜你喜欢
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 2019-05-08
    • 2017-05-28
    • 1970-01-01
    • 2019-10-19
    相关资源
    最近更新 更多