我希望允许用户在他们正在变异的状态实际可用之前编写变异函数,并且我创建了一个更高阶的函数,称为MutationIdentity:
type MutationIdentity<T, P extends any[]> = (state: T) => (...args: P) => T;
这表示了一种类型,该类型代表T正在变异的状态和P内部函数中的参数。虽然我发现它是身份突变的预期形状的有用表达(对不起,如果这是不精确的功能语言......我对术语相对较新),但由于 Typescript 的限制,它不能直接推断。
因此,为了构建这些身份突变,我提出了以下功能:
function MutationIdentity<T>() {
return function <M extends MutationIdentity<T, P>, P extends any[]>(mutationFn: M) {
return mutationFn;
};
}
这允许对这些函数进行强类型构造,并返回上面引用的类型的隐式表示MutationIdentity:
type State = { foo: number, bar: number };
const incr = MutationIdentity<State>()(
s => (foo: number) => ({ ...s, foo: s.foo++ })
);
我有两个问题,但主要问题是......如果这个函数返回一个显式表示MutationIdentity<T,P>或隐式首选,它会更好吗?这可能吗?
为了清楚起见,incr上面定义的函数可以像这样显式键入:
const incr: MutationIdentity<State, [number]> = MutationIdentity<State>()(
s => (foo: number) => ({ ...s, foo: s.foo++ })
);
这不会导致打字问题,但只是该类型目前没有被强制转换为这种显式形式。
第二个问题更具风格,但是......人们认为共享名称MutationIdentity的类型和函数的定义是代码气味还是可以?命名很困难,函数返回同名的类型。无论如何,有兴趣对此发表看法。
包括打字测试在内的完整代码可以在这个操场上找到