![](/img/trans.png)
[英]How to make TypeScript infer number & types of arguments from an array
[英]How to make TS automatically infer type arguments on mapped types?
考虑以下代码( Playground ):
type Either<E, D> = ["error", E] | ["data", D]
type GenericTuple<T = any> = [T, ...T[]];
// [Either<E, D1>, Either<E, D2>, ...] -> Either<E, [D1, D2, ...]>
declare function mergeEithers<E, Ds extends GenericTuple>(
eithers: { [K in keyof Ds]: Either<E, Ds[K]> }
): Either<E, Ds>;
type MessageError = {message: string};
declare const either1: Either<MessageError, string>
declare const either2: Either<MessageError, number>
// unpacked: Either<unknown, [string, number]>
const unpacked = mergeEithers([either1, either2])
我们应该如何编写它以便 TS 自动推断unpacked
为Either<MessageError, [string, number]>
?
您正在尝试在mergeEithers
的类型签名中使用映射类型的推断。 我发现在这种情况下编译器并不总是能够提取所需数量的信息。 您正在传入一个类型为 { [K in eithers
{ [K in keyof Ds]: Either<E, Ds[K]> }
的值,并希望编译器可以从中推断出E
和Ds
。 一般来说,它可以用Ds
做一些合理的事情(因为它是同态映射)并且可能在你得到任何对E
有用的东西之前就放弃了。
在这种“向后”推断不可靠的情况下,我通常使用 go 进行蛮力“向前”推断:如果我希望编译器推断类型A
,我应该传入A
类型的值。 为此,我们将选择eithers
类型A
这往往会被正确推断。 然后我们将使用A
来计算所需的 output 类型,该类型以前称为Either<E, Ds>
:
declare function mergeEithers<A extends GenericTuple<Either<any, any>>>(
eithers: A
): Either<
Extract<A[number], ["error", any]>[1],
{ [K in keyof A]: Extract<A[K], ["data", any]>[1] }
>;
在这里,我使用Extract
实用程序类型来提取错误和联合的数据部分。 类型Extract<A[number], ["error", any]>[1]
应该是eithers
元组的所有可能不同的错误类型的并集,而类型Extract<A[K], ["data", any]>[1]
应该是eithers
元组的每个元素K
的数据类型。
让我们看看它是否有效:
const unpacked = mergeEithers([either1, either2])
// const unpacked: Either<MessageError, [string, number]>
看起来不错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.