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

标签 typescript generics mutable typescript3.0

我正在尝试编写一个深度递归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 Playground,因此您可以使用代码: Link to TypeScript Playground

最佳答案

我的建议是做这样的事情:

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 和可能的 elem,最简单的解决方案是传入一个同时包含 arrayelem 的对象,并对其深度可变版本进行操作。

只有您知道在 elem 以及 array 上调用 mutate() 是否可以接受,因为 的实现mutate() 被省略。我猜这将涉及这样的断言:

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

在这种情况下,我会说“谁在乎”您是在 elem 上调用 mutate(),还是只是断言 elem到 doSomething() 内的可变对应项。另一方面,如果您的实现涉及克隆,那么您应该考虑在 elem 上调用它是否有意义。

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

关于TypeScript:带有泛型的递归深度可变。错误:T 不可分配给 Mutable<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53832989/

相关文章:

string - 将字符串缩小为字符串文字联合

typescript - 如何在 Jest 的 globalSetup 函数中使用模块导入 (@) 和 TypeScript?

c# - 泛型可以用来定义 C# 方法中的可选参数吗?

javascript - NGXS 在 setState 中传播状态

javascript - Typescript Angular HTTP 请求仅获取最后结果

c# - 在没有不可变字段的类中覆盖 Object.GetHashCode() 时返回什么?

c++ - 如何修改 const 的私有(private)成员?

c++ - 有人可以解释这些编程术语 : reference semantics, 非线性可变状态吗?

c# - 在 C# 中序列化泛型类

c++ - 错误C++: ‘const_iterator’没有命名类型;