Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 函数和非函数类型之间的类型细化_Typescript - Fatal编程技术网

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');