我正在尝试编写一个深度递归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
,最简单的解决方案是传入一个同时包含 array
和 elem 的对象
,并对其深度可变版本进行操作。
只有您知道在 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/