Typescript 函数和非函数类型之间的类型细化
我有一个状态更新程序函数,它接收以前的状态,并允许您通过整个对象或函数更新程序设置新状态。例如Typescript 函数和非函数类型之间的类型细化,typescript,Typescript,我有一个状态更新程序函数,它接收以前的状态,并允许您通过整个对象或函数更新程序设置新状态。例如 const prevState = { x: 3 }; // Option A const nextState = updateState(prevState, { x: 4 }); // Option B const nextState = updateState(prevState, prevState => ({ x: prevState.x + 1 })); 我可以在Flow中输入这
const prevState = { x: 3 };
// Option A
const nextState = updateState(prevState, { x: 4 });
// Option B
const nextState = updateState(prevState, prevState => ({ x: prevState.x + 1 }));
我可以在Flow中输入这个,但无法再在TypeScript中工作。以下是函数:
function updateState<State>(
prevState: State,
updater: State | ((prevState: State) => State),
): State {
return typeof updater === 'function' ? updater(prevState) : updater;
}
函数更新属性(
国家:国家,
更新程序:State |((prevState:State)=>State),
):陈述{
返回更新程序的类型=='function'?更新程序(prevState):更新程序;
}
这就是错误:
无法调用缺少调用签名的whosetype表达式。类型“((prevState:State)=>State)|(状态和函数)”没有兼容的调用签名
(状态和功能)
来自哪里
我的理解是,State
本身也可以是一个函数,因为State
是非类型化的。但也许我可以将状态限制为非函数类型
有什么方法可以在TypeScript中工作吗?问题在于状态
是一个泛型类型参数,因此没有理由状态
不能成为函数。因此,当您使用类型保护时,缩小的结果不能从类型中排除State
。类型守卫所能说的是,新类型也将是一个函数,这意味着与函数
相交的原始类型,它遵循如何扩展这些类型的规则:(State |((prevState:State)=>State))&function=(State&function)((prevState:State)=>State&function)=(状态和功能)|(((prevState:State)=>State))
我们可以做的一件事是确保State
与函数不兼容(没有明确的方法说泛型类型不能是特定类型,我们只能说类型可以是什么)
extends{call?:never}
太棒了。谢谢!这个想法很有趣,但似乎不管用?尝试使用这个函数失败了。@JonRimmer编辑了答案,原语有一个问题,但除了原语值之外,它也可以用于原语值,{call?:never}
不适用于对象--空对象除外。对象中的任何属性都将生成类型为“{x:number;}”的参数,该参数不可分配给类型为“{call?:undefined;}”的参数。
我发现{call?:never,[key:string]:Any;}一个可扩展的工作替代品。你认为它是可行的解决方案吗?@ Trsimik HM,我确信它是在我写的时候起作用的。修改代码使它能用3.3。10x来指出它,有时错误要么错误地要么由于TS改变而蠕变:
function updateState<State extends { call?: never } & Record<string, any>>( // if State has a call member it must be never
prevState: State,
updater: State | ((o: State) => State),
): State {
return typeof updater === "function" ? updater(prevState) : updater;
}
function foo<S extends string | number | boolean | null | undefined | { call?: never }>(initial: S | (() => S)): S {
return typeof initial === 'function' ? initial() : initial;
}
foo('test');