【问题标题】:Type safe deep update: could be instantiated with an arbitrary type which could be unrelated类型安全的深度更新:可以用可能不相关的任意类型实例化
【发布时间】:2021-02-13 10:09:08
【问题描述】:

有什么办法可以去掉update_substate函数中的as any?直接调用 update_state 函数时它是类型安全的,所以间接调用也应该是安全的吗?这些是 Redux 状态的轻量级辅助函数。我已经阅读了一些相关的问题([1][2][3]),但还不了解解决方案。

export function update_state <
    RootState,
    P1 extends keyof RootState,
    S1 extends RootState[P1],
> (root_state: RootState, path1: P1, replacement_state: S1)
{
    const current = root_state[path1]
    if (current === replacement_state) return root_state

    return {
        ...root_state,
        [path1]: replacement_state
    }
}


export function update_substate <
    RootState,
    P1 extends keyof RootState,
    S1 extends RootState[P1],
    P2 extends keyof S1,
    S2 extends S1[P2],
> (root_state: RootState, path1: P1, path2: P2, replacement_substate: S2)
{
    /**
    Without the `as any` will get the error:

    Argument of type 'RootState[P1]' is not assignable to parameter of type 'S1'.
    'S1' could be instantiated with an arbitrary type which could be unrelated to 'RootState[P1]'.
        Type 'RootState[keyof RootState]' is not assignable to type 'S1'.
        'S1' could be instantiated with an arbitrary type which could be unrelated to 'RootState[keyof RootState]'.
            Type 'RootState[string] | RootState[number] | RootState[symbol]' is not assignable to type 'S1'.
            'S1' could be instantiated with an arbitrary type which could be unrelated to 'RootState[string] | RootState[number] | RootState[symbol]'.
                Type 'RootState[string]' is not assignable to type 'S1'.
                'S1' could be instantiated with an arbitrary type which could be unrelated to 'RootState[string]'.ts(2345)
    */
    const replacement_state = update_state<S1, P2, S2>(root_state[path1] as any, path2, replacement_substate)
    return update_state(root_state, path1, replacement_state)
}

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这是一种使 sn-p 编译的方法(无需检查其内容):

    1. 省略类型参数S1,因为它没有在update_substate函数签名中使用。
    2. 让参数类型自动推断,无需使用update_state&lt;S1, P2, S2&gt; 声明它们。
    3. P2 的通用约束更新为P2 extends keyof RootState[P1]
    export function update_substate <
        RootState,
        P1 extends keyof RootState,
        P2 extends keyof RootState[P1],
        S2 extends RootState[P1][P2],
    > (root_state: RootState, path1: P1, path2: P2, replacement_substate: S2)
    {
        const replacement_state = update_state(root_state[path1], path2, replacement_substate)
        return update_state(root_state, path1, replacement_state)
    }
    

    Live code

    【讨论】:

    • 非常感谢您的快速答复和解决方案。它工作得很好。是的,我认为“省略类型参数 xyz,因为它没有在函数签名中使用”是一个很好的气味测试。
    猜你喜欢
    • 2021-10-26
    • 2020-11-28
    • 1970-01-01
    • 2021-05-11
    • 2021-06-23
    • 1970-01-01
    • 2021-01-19
    • 2021-04-10
    • 2021-09-21
    相关资源
    最近更新 更多