TypeScript:使用泛型的递归深度可变。错误:T不可分配给可变<;T>;
我正在尝试编写一个深度递归TypeScript:使用泛型的递归深度可变。错误:T不可分配给可变<;T>;,typescript,generics,mutable,typescript3.0,Typescript,Generics,Mutable,Typescript3.0,我正在尝试编写一个深度递归可变类型: 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>) => v
可变类型:
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
}
Mutable=。。。
//删除所有“只读”修改器
//将所有只读数组转换为数组
//等等。
//然后递归地完成这一切
常量mutate=(val:T,mutateFn:(mutableVal:Mutable)=>void:T=>{
返回null作为任意值
}
只要我不使用泛型,它就可以正常工作:
// works fine
mutate([] as ReadonlyArray<string>, mutableVal => {
mutableVal.splice(42, 0, "test");
});
//很好用
变异([]为只读数组,可变值=>{
可变值拼接(42,0,“测试”);
});
但在泛型函数中使用它时,我会得到一个错误:
// 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);
});
}
//错误:“T”类型的参数不可分配给“Mutable”类型的参数。
常量doSomething=(数组:ReadonlyArray,索引:number,元素:T)=>{
mutate(数组,mutableVal=>{
//这是错误
//五
可变值拼接(索引,0,元素);
});
}
我知道可变数组的类型是array
,而splice
现在需要的是mutable
值,而不是T
。但我不知道怎么解决它
你知道怎么解决这个问题吗
我已经创建了一个TypeScript游戏场,因此您可以使用以下代码:
我的建议是这样做:
const doSomething = <T>(array: ReadonlyArray<T>, index: number, elem: T) => {
mutate({ array: array, elem: elem }, mutableVal => {
mutableVal.array.splice(index, 0, mutableVal.elem);
});
}
const doSomething=(数组:ReadonlyArray,索引:number,元素:T)=>{
mutate({array:array,elem:elem},mutableVal=>{
mutableVal.array.splice(索引,0,mutableVal.elem);
});
}
这个想法是,您需要elem
是可变的,以便将其添加到深度可变数组中,但您最初的调用并没有这样做。由于您希望同时变异数组
和元素
,因此最简单的解决方案是传入一个同时包含数组
和元素
的对象,并对该对象的深层可变版本进行操作
只有您知道在elem
和array
上调用mutate()
是否可以接受,因为mutate()
的实现被省略了。我猜这会涉及到这样的断言:
const doSomething = <T>(array: ReadonlyArray<T>, index: number, elem: T) => {
mutate({ array: array, elem: elem }, mutableVal => {
mutableVal.array.splice(index, 0, mutableVal.elem);
});
}
constmutate=(val:T,mutateFn:(mutableVal:Mutable)=>void:T=>{
mutateFn(val为可变值)/T
和Mutable
显然不兼容,但您想如何处理这一点?简单的选择是将elem
键入为Mutable
。另一个选择是不在数组上执行深度Mutable…这在很大程度上取决于您的用例,您想做什么我不确定如何处理,这就是为什么我要创建此问题。T
和Mutable
应始终具有相同的结构:{readonly foo:string}
变为{foo:string}
。并且只读数组
变成数组
。用例就像我发布的代码中的mutate
函数。但是在某些情况下,我想在另一个函数中使用mutate
函数(比如doSomething
)然后它就不起作用了。当然我可以把元素写成可变的,它工作得很好。但我希望能找到一个现成的解决方案。这也是一个可能的解决方案。谢谢。基本上mutate
函数应该是一个对象(或数组)可变。elem
不需要是可变的,如果你只想改变数组。如果你想改变elem
,你可以调用mutate(elem,…)
。或者如果你想改变两者,你可以为两者调用mutate
(,或者在你的代码中:创建一个新对象,两者都在里面)。有很多解决方案(,你甚至可以像任何地方的任何人一样使用)。我只是认为可能会保持简单,让TypeScript在幕后完成它的工作。“如果你只想改变数组,那么元素不必是可变的。”但是你不能将一个不可变元素添加到一个深度可变数组中,对吗?这就是为什么它是“深度”的原因。如果您只想对数组进行变异,而不要求其内容也是可变的,那么您只需要一个普通的数组
,而不是数组
,这就是可变的
的形式。在我听来,您确实想要一些不一致的东西。您的选择是制作一个简单可变的数组
(这意味着你不能调用mutate()
,正如上面在array
上定义的那样),制作一个可变版本的elem
(这意味着你需要在array
和elem
上调用mutate()
),或者你只需要通过调用mutate()来声明你的出路
仅在array
上传递elem作为可变的
而不是elem
。但是在最后一种情况下,您必须故意使(有效的)编译器消息静音,警告您正在尝试执行不安全的操作。是的,这是真的。我还没有考虑过这种情况。。。“如果您将一个不可变的元素
添加到可变的数组
中,然后尝试对该元素进行变异,会怎么样?“我的第一个想法是:即使在将元素添加到数组中后,也禁止对其进行变异。但是之前数组中的所有内容都应该是可变的。也许我需要再睡一晚:D无论如何:谢谢你的提示!