gpt4 book ai didi

typescript - 如何实现泛型 First "case/switch"类型

转载 作者:搜寻专家 更新时间:2023-10-30 21:32:33 25 4
gpt4 key购买 nike

我目前正在重构 redux-starter-kit 的类型,以使其对非 typescript-powerusers 更具可读性。

现在,它看起来像这样:

 type PayloadActionCreator<
P = any,
T extends string = string,
PA extends PrepareAction<P> | void = void
> =
IfPrepareActionMethodProvided<PA,
ActionCreatorWithPreparedPayload<PA, T>,
IfMaybeUndefined<P,
ActionCreatorWithOptionalPayload<P, T>,
IfVoid<P,
ActionCreatorWithoutPayload<T>,
ActionCreatorWithPayload<P, T>
>
>
>

但我想取消嵌套并希望实现这样的目标:

type PayloadActionCreator<
P = any,
T extends string = string,
PA extends PrepareAction<P> | void = void
> =
First<
IfPrepareActionMethodProvided<PA, ActionCreatorWithPreparedPayload<PA, T>, void>,
IfMaybeUndefined<P, ActionCreatorWithOptionalPayload<P, T>, void>,
IfVoid<P, ActionCreatorWithoutPayload<T>, void>,
ActionCreatorWithPayload<P, T>
>;

因此,First 应该是一个接受多个类型并返回其中第一个不是 void

的类型

我已经实现了一个简单的 First 版本,它运行良好,直到将具有泛型(如 IfVoid)的类型传递给它。然后我开始处理返回 void 的情况,即使后面的选项不是 void - 请参阅此代码:

type FallbackIfNotVoid<Type,  False> = [Type] extends [void] ? False : Type;

type First<
A = void,
B = void,
C = void,
D = void
> =
FallbackIfNotVoid<A,
FallbackIfNotVoid<B,
FallbackIfNotVoid<C,
FallbackIfNotVoid<D, void>
>>>;


type IfVoid<P, True, False = void> = [void] extends [P] ? True : False;

type Experiment<T> = First<
IfVoid<T, "voidCase">,
T
>;

type VoidType = Experiment<void>; // "voidCase", as expected
type OtherType = Experiment<"test"> // this should be "test", but is void

我猜这是因为 TS 做了一些预优化,但后来适得其反。将鼠标悬停在类型上表示我的类型定义已优化为 [void] extends [T] ? “voidCase”:void

有人知道如何实现这样的 First 类型吗?

最佳答案

这是一个 typescript 错误。

首先是解决方法,如果我们从条件类型中取出 void 并将其放入类型别名的类型参数中:

type FallbackIfNotVoid<Default, Type, False> = [Type] extends [Default] ? False : Type;

type First<
Default = void,
A = void,
B = void,
C = void,
D = void> =
FallbackIfNotVoid<Default, A,
FallbackIfNotVoid<Default, B,
FallbackIfNotVoid<Default, C,
FallbackIfNotVoid<Default, D, Default>>>>;


type IfVoid<P, True, False = void> = [void] extends [P] ? True : False;

type Experiment<T, Default = void> = First<Default,
IfVoid<T, "voidCase">,
T
>;

type VoidType = Experiment<void>; // "voidCase", as expected
type OtherType = Experiment<"test"> // "test" now

现在对于错误,这是一个最小的复制:

type Default = { x: string }

type M<A> = [A extends "A" ? A : Default] extends [Default] ? "Y" : "N" // Simplified to "Y" regardless of A

M 简化为 "Y"。如果测试类型 ([A extends "A"? A : Default]) 也是条件类型,并且如果该条件类型在错误分支中包含在外部测试的类型,则会发生这种情况条件类型。这只发生在错误的分支上。例如,下面的类型没有得到类似的简化:

type Default = { x: string }

type M<A> = [A extends "A" ? Default: A] extends [Default] ? "Y" : "N" // no simplification

Default 放在类型参数中可以解决这个问题,因为它可以防止这种急切的优化。

我将搜索现有问题并在找到后发布。我 100% 肯定我见过与条件类型简化相关的类似问题,只是不确定它们是否就是这个问题。

编辑:是的,我是对的,我以前确实看到过类似的东西,甚至参与过关于它的谈话(年纪大了健忘🙃)Here是问题所在,jack-williams 也有类似的 repro:

type Inner<T> = [T] extends [true] ? false : true;
type Outer<T> = [Inner<T>] extends [true] ? 1 : 2; // Already resolved to 2.

关于typescript - 如何实现泛型 First "case/switch"类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57299572/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com