首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >函数和非函数类型之间的类型细化

函数和非函数类型之间的类型细化
EN

Stack Overflow用户
提问于 2018-12-04 17:11:14
回答 1查看 61关注 0票数 2

我有一个状态更新器函数,它接收以前的状态,并允许您通过整个对象或函数更新器来设置新状态。例如:

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 & Function)是从哪里来的?

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

有没有办法在TypeScript中做到这一点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-04 17:34:59

问题在于State是一个泛型类型参数,所以没有理由State不能是一个函数。因此,当您使用类型保护时,缩小范围的结果不能将State排除在类型之外。类型保护可以说的是,新类型也将是一个函数,这意味着原始类型与Function相交,遵循这些类型如何扩展的规则,我们得到:(State | ((prevState: State) => State)) & Function = (State & Function) | (((prevState: State) => State) & Function ) = (State & Function) | (((prevState: State) => State))

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

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成为一个原语,你需要用一个联合来添加原语:

function foo<S extends string | number | boolean | null | undefined | { call?: never }>(initial: S | (() => S)): S {
    return typeof initial === 'function' ? initial() : initial;
}

foo('test');
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53609286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档