【发布时间】:2019-05-18 20:50:52
【问题描述】:
我正在尝试编写一个深度递归的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
【问题讨论】:
-
T和Mutable<T>显然不兼容,但是您想如何处理呢?简单的选择是将elem键入为Mutable<T>。另一种方法是不要对数组进行深度可变...很大程度上取决于您的用例您想要做什么 -
我不确定如何处理这个问题,这就是我创建这个问题的原因。
T和Mutable<T>应该始终具有相同的结构:{ readonly foo: string }变为{ foo: string }。ReadonlyArray<Foo>变为Array<Foo>。用例就像我发布的代码中一样:mutate函数。但在某些情况下,我想在另一个函数(如doSomething)中使用mutate函数,然后它就不再起作用了。当然我可以写elem as Mutable<T>,它工作正常。但我希望找到一些开箱即用的解决方案。
标签: typescript generics mutable typescript3.0