我如何让 Typescript 知道我的函数将克隆一个传递的只读保护参数?
How can I let Typescript know, that my function will clone a passed Readonly protected argument?
我想知道如何让 Typescript 理解 update 可以被作为第二个参数传递给 modifyState 的函数改变,因为 update 将被克隆。
// Basic example
import { clone } from 'lodash';
interface IState {
foo: string;
}
const state: Readonly<IState> = {
foo: "bar"
};
// Start situation
function modifyState<S>(
prevState: S,
updateFunc: (update: S) => void
): S {
const newState = clone(prevState);
updateFunc(newState);
return newState;
}
modifyState(
state,
update => {
update.foo = "another string"; // 'Cannot assign to 'foo' because it is a constant or a read-only property.'
}
);
您可以从接收到的 Readonly<T>
值的泛型类型参数中推断出泛型类型:
function modifyState<S>(
prevState: Readonly<S>, // <- this one
updateFunc: (update: S) => void
): Readonly<S> {
...
}
我相信密码是 self-explanatory。如果需要同时支持 readonly
和 non-readonly 版本,可以使用重载签名,或者联合类型,例如:
prevState: Readonly<S> | S
在这种情况下,TypeScript 编译器将 Readonly<S>
优先于 S
,如果适用的话。
您可以使用这种方法:
type Mutable<T extends { [x: string]: any }, K extends string> = {
[P in K]: T[P];
}
...
updateFunc: (update: Mutable<S, keyof S>) => void
我想知道如何让 Typescript 理解 update 可以被作为第二个参数传递给 modifyState 的函数改变,因为 update 将被克隆。
// Basic example
import { clone } from 'lodash';
interface IState {
foo: string;
}
const state: Readonly<IState> = {
foo: "bar"
};
// Start situation
function modifyState<S>(
prevState: S,
updateFunc: (update: S) => void
): S {
const newState = clone(prevState);
updateFunc(newState);
return newState;
}
modifyState(
state,
update => {
update.foo = "another string"; // 'Cannot assign to 'foo' because it is a constant or a read-only property.'
}
);
您可以从接收到的 Readonly<T>
值的泛型类型参数中推断出泛型类型:
function modifyState<S>(
prevState: Readonly<S>, // <- this one
updateFunc: (update: S) => void
): Readonly<S> {
...
}
我相信密码是 self-explanatory。如果需要同时支持 readonly
和 non-readonly 版本,可以使用重载签名,或者联合类型,例如:
prevState: Readonly<S> | S
在这种情况下,TypeScript 编译器将 Readonly<S>
优先于 S
,如果适用的话。
您可以使用这种方法:
type Mutable<T extends { [x: string]: any }, K extends string> = {
[P in K]: T[P];
}
...
updateFunc: (update: Mutable<S, keyof S>) => void