如何关联在高阶函数之间定义的泛型类型? [英] How do I relate the generic types defined between higher-order functions?

查看:105
本文介绍了如何关联在高阶函数之间定义的泛型类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个Redux存储增强器,该增强器具有用于序列化Redux状态的功能.我将构建存储并为变更设置订阅-在每个变更上,我将序列化状态.对于此MCVE,我将忽略订阅方面,而只是立即调用序列化函数.

I am creating a Redux store enhancer that takes in a function to serialize the Redux state. I'll construct the store and set up a subscription for changes — on each change, I'll serialize the state. For this MCVE, I'm ignoring the subscription aspect and just immediately calling the serialization function.

但是,由于函数的高阶性质,我无法将状态的通用类型(需要序列化功能)与商店创建者返回的通用类型相关联:

However, due to the higher-order nature of the function, I'm unable to correlate my generic type for the state (needed for the serialization function) with the generic type returned by the store creator:

// Copied and reduced from Redux 4.0.1

type Reducer<S = any> = (
  state: S | undefined,
) => S

type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> }

interface Store<S = any> {
  getState(): S
}

type StoreEnhancer<Ext = {}, StateExt = {}> = (
  next: StoreEnhancerStoreCreator
) => StoreEnhancerStoreCreator<Ext, StateExt>

type StoreEnhancerStoreCreator<Ext = {}, StateExt = {}> = <
  S = any,
>(
  reducer: Reducer<S>,
  preloadedState?: DeepPartial<S>
) => Store<S & StateExt> & Ext

// My reduced code

interface Config<S> {
  serialize: (state: S) => string;
}

const storage = <S>(config: Config<S>): StoreEnhancer => createStore => (reducer, preloadedState) => {
  const { serialize } = config;

  const theStore = createStore(reducer, preloadedState);

  const state = theStore.getState();
  const serializedState = serialize(state);

  return theStore;
}

(错误是:

const serializedState = serialize(state);
                                  ^~~~~

Argument of type 'S & {}' is not assignable to parameter of type 'S'.

错误消息很烦人,因为我很确定两个S是不相关的.更改StoreEnhancerStoreCreator中的定义以使用X而不是S会更改此错误消息.

The error message is annoying because I'm pretty sure that the two S are unrelated; changing the definition in StoreEnhancerStoreCreator to use X instead of S changes this error message.

如何将我的通用类型参数与StoreEnhancerStoreCreator上定义的通用参数连接?

How can I connect my generic type parameter with the generic parameter defined on StoreEnhancerStoreCreator?

推荐答案

我同意@ matt-mccutchen指出的问题. StoreEnhancerStoreCreator是泛型函数,所以(reducer, preloadedState) => {是带有S泛型类型参数的泛型函数,这就是为什么编译器报告两种S类型之间不兼容的原因.

I agree with the problem identified by @matt-mccutchen. StoreEnhancerStoreCreator is a generic function, so (reducer, preloadedState) => { is a generic function with an S generic type argument, this is why the compiler reports the incompatibility between the two S types.

我将提出的解决方案是StoreEnhancerStoreCreator不是通用的,据我所知,reducer和有效负载应具有与Config相同的通用类型参数.此解决方案需要在StoreEnhancerStoreCreatorStoreEnhancer中添加一个额外的类型参数:

The solution I would propose would be for StoreEnhancerStoreCreator to not be generic, from what I can tell the reducer and the payload should have the same generic type argument as the Config. This solution requires adding an extra type parameter to StoreEnhancerStoreCreator and StoreEnhancer:

type Reducer<S = any> = (
  state: S | undefined,
) => S

type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> }

interface Store<S = any> {
  getState(): S
}

type StoreEnhancer<S, Ext = {}, StateExt = {}> = (
  next: StoreEnhancerStoreCreator<S>
) => StoreEnhancerStoreCreator<S, Ext, StateExt>

type StoreEnhancerStoreCreator<S, Ext = {}, StateExt = {}> = (
  reducer: Reducer<S>,
  preloadedState?: DeepPartial<S>
) => Store<S> & Ext

// My Code

interface Config<S> {
  serialize: (state: S) => string;
}

const storage = <S>(config: Config<S>): StoreEnhancer<S> => createStore => (reducer, preloadedState) => {
  const { serialize } = config;

  const theStore = createStore(reducer, preloadedState);

  const state = theStore.getState();
  const serializedState = serialize(state);

  return theStore;
}

这篇关于如何关联在高阶函数之间定义的泛型类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆