如何在TypeScript中动态更新键入对象上的键值对

时间:2020-07-20 02:25:48

标签: reactjs typescript

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

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'。 在类型'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>
    )
}

2 个答案:

答案 0 :(得分:4)

TLDR ;

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

详细信息

给予

interface X {
  prop: number;
  other: string;
}

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

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

由于该语言知道dataToUpdate的唯一键是"prop""other",因此必须相应地限制更新功能的key参数。

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

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

但是,我们尚未完成,因为该语言需要确保value参数的类型与指定的key的属性类型(以及恰好与{{1 }}必须是"prop",而number必须是"other"

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

string

我们所做的是关联两个参数的类型,以使updateKey<K extends keyof X>(key: K, value: X[K]) 的类型与value指定的属性的类型匹配,无论何时调用该函数。

答案 1 :(得分:1)

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

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