如何在 TypeScript 中动态更新类型化对象上的键值对

Sha*_*ger 6 typescript reactjs

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

使用以下代码链接到代码沙箱

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

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

function updateKey(key : string, value : number | string) {
    dataToUpdate[key] = value;
}
Run Code Online (Sandbox Code Playgroud)

我通过上述实现收到此错误。

元素隐式具有'any'类型,因为 type 的表达式'string'不能用于索引 type 'x''string'在类型上找不到带有类型参数的索引签名'x'。(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>
    )
}
Run Code Online (Sandbox Code Playgroud)

Alu*_*dad 9

太长了

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

细节

给定

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

const dataToUpdate: X = {
    prop: 1,
    other: "string"
};
Run Code Online (Sandbox Code Playgroud)

TypeScript 不允许我们通过任意属性键dataToUpdate类型(例如 )访问具有一组已知属性(例如您的 )的类型正确的对象的属性string

由于该语言知道 的唯一键dataToUpdate"prop""other",因此更新函数的键参数必须受到相应的限制。

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

updateKey(key: keyof X, value: string | number) {
  dataToUpdate[key] = value; 
}
Run Code Online (Sandbox Code Playgroud)

然而,我们还没有完成,因为语言需要确保参数的类型value与指定的属性类型相对应key,并且碰巧"prop"必须是 anumber并且"other"必须是 a string

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

updateKey<K extends keyof X>(key: K, value: X[K])
Run Code Online (Sandbox Code Playgroud)

我们所做的是将两个参数的类型关联起来,以便每当调用函数时,的类型value与 指定的属性类型相匹配。key