功能和非功能类型之间的类型细化

时间:2018-12-04 09:11:14

标签: 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中键入此内容,但不能再使其在TypeScript中工作。这是函数:

function updateState<State>(
  prevState: State,
  updater: State | ((prevState: State) => State),
): State {
  return typeof updater === 'function' ? updater(prevState) : updater;
}

这是错误:

  

无法调用类型缺少调用签名的表达式。类型'(((prevState:State)=> State)| (状态和功能)'没有兼容的呼叫签名。

(State & Function)来自哪里?

我的理解是State本身也可以是一个函数,因为State是无类型的。但是也许我可以将State限制为非功能类型...

有什么办法可以使它在TypeScript中起作用?

1 个答案:

答案 0 :(得分:2)

问题在于State是泛型类型参数,因此没有理由State不能是函数。因此,当您使用类型保护器时,缩小的结果不能从类型中排除State。类型守卫可以说的是,新类型也将是一个函数,这意味着原始类型与Function相交,遵循如何扩展这些类型的规则,我们得到:{{1 }}

我们可以做的一件事是确保(State | ((prevState: State) => State)) & Function = (State & Function) | (((prevState: State) => State) & Function ) = (State & Function) | (((prevState: State) => State))与Function不兼容(没有明确的方法可以说泛型类型不能是特定类型,我们只能说一个类型可以是什么类型) )。

State

该解决方案的一个缺点是约束基本上迫使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; } 成为对象。如果您还希望State成为基本体,则需要通过并集将基本体添加回去:

State