我正在为OSS JS项目定义类型定义,并且需要在类型别名中推断“内部”类型。
有一种特定的类型可以是:
ActionFunc<State, Payload> = (state: State, payload: Payload) => State
直接从给定事件中获取有效负载。如果要将负载状态与自己的本地数据组合成不同负载类型,则可以改用:
[ActionFunc<State, ??>, (data: Payload) => ?]
这是一个在相同状态下包含AnctionFunc
,但具有不同有效负载参数的元组,可以通过首先应用第二个元组来生成可以从常规Payload
类型映射到自定义类型的项目。
该类型别名的天真版本类似于:
type Action<State, StandardPayload = {}, CustomPayload = void> =
| ActionFunc<State, StandardPayload>
| [ActionFunc<State, CustomPayload>, (payload: StandardPayload) => CustomPayload]
但是我遇到的问题是,它在外部公开了CustomPayload
参数,从理论上讲应该可以推断并在内部一致地使用它,例如:
type Action<State, StandardPayload = {}> =
| ActionFunc<State, StandardPayload>
| [ActionFunc<State, infer CustomPayload>, (payload: StandardPayload) => CustomPayload]
只要ActionFunc
和payload composer
函数的参数类型 match ,我们就不在乎该类型是消费者/调用者。
当前的TS仅在infer
条件类型的上下文中允许extends
,但在这里我无法弄清楚哪种条件真正有意义。
答案 0 :(得分:1)
您想要existentially quantified generic types,它们是not directly implemented in TypeScript(或其他大多数具有泛型的语言,以确保其价值。如果为{{3}启用语言扩展,甚至Haskell也只有supports them }}。)TypeScript仅具有 universally 量化的通用类型;像Foo<T>
这样的通用量化泛型类型的实现/定义需要能够处理该类型的调用者/用户想要的T
的任何可能值。存在类型会反过来:存在限定条件的通用类型(如(虚构语法)exists T. Foo<T>
)的 caller / user 必须能够处理{{1}的任何可能值} 实现/定义想要的。从呼叫者的角度来看,您只能指定T
对应于 some 类型(现有),而不是 any 类型(通用)。
那么,在没有直接支持存在的情况下,我们可以在TypeScript中做什么?好吧,我们可以通过反转带有函数和回调的控制来获得间接支持,这实际上将通用性转换为存在性,反之亦然。将其视为处理诸如承诺之类的东西,而不是处理其本身的价值:
T
这隐藏了type ActionPair<S, P, C> = [ActionFunc<S, P>, (payload: P) => C];
type ActionPairPromise<S, P> = {
then<R>(onfulfilled: <C>(value: ActionPair<S, P, C>) => R): R;
};
参数,但是要使用它,您将必须在各处传递回调:
C
还有其他方法来代替存在性...您可以按照您所说的使用// turn a concrete ActionPair<S, P, C> into the existential ActionPairPromise<S, P>
function actionPairToActionPairPromise<S, P, C>(
actionPair: ActionPair<S, P, C>
): ActionPairPromise<S, P> {
return {
then(onfulfilled) {
return onfulfilled(actionPair);
}
};
}
// take the existential ActionPairPromise<S, P> and do something with it
// namely, convert into an ActionFunc
function actionPairPromiseToActionFunc<S, P>(
value: ActionPairPromise<S, P>
): ActionFunc<S, P> {
return value.then(actionPair => (state: S, payload: P) =>
actionPair[0](state, actionPair[1](payload))
);
}
,然后使接受此类类型的所有函数通用,并进行额外的检查以确保它符合某些类型any
参数...
但是我在这里强烈怀疑,归根结底,使用C
可以做到的唯一一件事就是将其转换为{{1 }}。那么为什么不这样做呢?
ActionPairPromise<S, P>
也就是说,您使用该类型的唯一位置是在转换为普通ActionFunc<S, P>
并完成此操作的函数中。
无论如何,希望能帮到您一些想法。祝你好运!