代码之家  ›  专栏  ›  技术社区  ›  Benjamin M

TypeScript:使用泛型的递归深度可变。错误:T不可分配给可变<T>

  •  2
  • Benjamin M  · 技术社区  · 6 年前

    我正试图写一个深度递归 Mutable

    Mutable<T> = ...
        // remove all "readonly" modifiers
        // convert all ReadonlyArray to Array
        // etc.
        // and do it all recursively
    
    const mutate = <T>(val: T, mutateFn: (mutableVal: Mutable<T>) => void): T => {
      return null as any
    }
    

    只要我不使用泛型,它就可以正常工作:

    // works fine
    mutate([] as ReadonlyArray<string>, mutableVal => {
      mutableVal.splice(42, 0, "test");
    });
    

    但在泛型函数中使用它时,我会得到一个错误:

    // Error: Argument of type 'T' is not assignable to parameter of type 'Mutable<T>'.
    const doSomething = <T>(array: ReadonlyArray<T>, index: number, elem: T) => {
      mutate(array, mutableVal => {
                          // Here's the error
                          //         v
        mutableVal.splice(index, 0, elem);
      });
    }
    

    我知道,可变数组的类型是 Array<Mutable<T>> ,而且 splice 现在期待一个 Mutable<T> 价值,而不是 T

    你知道怎么解决这个问题吗?

    我已经创建了一个TypeScript游戏场,因此您可以使用以下代码: Link to TypeScript Playground

    1 回复  |  直到 6 年前
        1
  •  2
  •   jcalz    6 年前

    我的建议是这样做:

    const doSomething = <T>(array: ReadonlyArray<T>, index: number, elem: T) => {
        mutate({ array: array, elem: elem }, mutableVal => {
            mutableVal.array.splice(index, 0, mutableVal.elem);
        });
    }
    

    这个想法是你需要 elem 为了将它添加到一个深度可变数组中,而您最初的调用并没有做到这一点。既然你想两者都变异 array 还有可能 元素 元素 ,并对其深层可变版本进行操作。

    mutate() 元素 以及 ,自 突变 他被遗漏了。我猜这会涉及到这样的断言:

    const mutate = <T>(val: T, mutateFn: (mutableVal: Mutable<T>) => void): T => {
        mutateFn(val as Mutable<T>); //🤷‍♀️
        return val;
    }
    

    突变 在…上 元素 到其内部可变的对应物 doSomething() . 另一方面,如果您的实现涉及到克隆,那么您应该考虑调用它是否有意义 或者不是。

    好的,希望能有帮助。祝你好运