如何在Typescript中遍历异构对象

s6fujrry  于 2023-02-17  发布在  TypeScript
关注(0)|答案(2)|浏览(135)

我有一个状态对象和一个将与状态对象组合在一起的更新对象,尽管更新中的null意味着删除,所以我不能只对它们执行{...a, ...b}

const obj = {
    other: new Date(),
    num:5,
    str:"original string"
}

const objUpdate:Partial<typeof obj> = {
    num:6,
    str:"updated string"
}

任务:迭代更新对象并将其值应用于原始对象,这是我理想的做法:

Object.entries(objUpdate).forEach(([k,v])=>{
    if (v === undefined) return;
    if (v === null){
        delete obj[k]; // <-
        return;
    }
    obj[k] = v; // <-
})

但是在指定的行我得到一个错误No index signature with a parameter of type 'string' was found on type '{ other: Date; num: number; str: string; }'。理想情况下,Typescript应该知道k已经是keyof typeof objUpdate(编辑:here's possibly why),但我想我可以明确指出:

Object.entries(objUpdate).forEach(([k,v])=>{
    if (v === undefined) return;
    if (v === null){
        delete obj[k as keyof typeof objUpdate];
        return;
    }
    obj[k as keyof typeof objUpdate] = v; // <-
})

在指示行,它抱怨Type 'string | number | Date' is not assignable to type 'never'. Type 'string' is not assignable to type 'never'.
1.在这种情况下,有没有办法帮助Typescript正确地推断打字?
1.有没有更好的方法来实现我正在努力实现的目标?

hwamh0ep

hwamh0ep1#

动态删除对象上的键在JavaScript中速度很慢,而且会使TypeScript中的键入变得更加困难。最简单的方法是调整代码中引用状态的其他部分,以便它们检查值是否为null

const obj = {
    other: <someDate>,
    str: <someString>
}

就会有

const obj = {
    other: <someDate>,
    num: null,
    str: <someString>
}

使用这种方法,输入将 * 正常工作 *,并且状态更新 * 将 * 像{...a, ...b}一样微不足道。
要键入初始状态,请将键Map到添加了null的新对象类型。

const obj = {
    other: new Date(),
    num:5,
    str:"original string"
}
type Obj = typeof obj;
type ObjState = {
  [K in keyof Obj]: Obj[K] | null;
};

// ...

const [stateObj, setStateObj] = useState<ObjState>(obj);
// Update:
setStateObj({ ...stateObj, ...objUpdate });

如果代码的某个部分要求删除null属性来格式化对象(例如数据库查询),可以在发送对象之前 * 在必要时 * 创建一个新对象,而不是更改状态的形状。

const objWithNullPropertiesRemoved: Partial<Obj> = Object.fromEntries(
  Object.entries(stateObj)
    .filter(([, val]) => val !== null)
);
// send the objWithNullPropertiesRemoved somewhere
vsnjm48y

vsnjm48y2#

我接受的答案对大多数人来说很可能是正确的方法,但我只是找到了一种方法来让我最初的方法工作,并在这里提供它的完整性。
使用Transform union type to intersection type,然后将值v键入为as UnionToIntersection<typeof obj[keyof typeof obj]>

相关问题