元组成员的映射类型



我正在尝试创建一个映射元组,它可以深入到成员的类型:

export type Argument<T = unknown> = {
value: T;
};
export type TypesOf<T extends Argument[]> = {[Index in keyof T]: T[Index]["value"]};

因此,TypesOf<[{value: number}, {value: string}]>应该生成[number, string]

但是,我得到这个错误:

Type '"value"' cannot be used to index type 'T[Index]'.

编辑:

应用@jcalz的解决方案后的附加问题:

const tuple = [{value: 1}, {value:"foo"}] as const;
type V = TypesOf<typeof tuple>;

I get error:

Type 'readonly [{ readonly value: 1; }, { readonly value: "foo"; }]' does not satisfy the constraint 'Argument<unknown>[]'.
The type 'readonly [{ readonly value: 1; }, { readonly value: "foo"; }]' is 'readonly' and cannot be assigned to the mutable type 'Argument<unknown>[]'.

您所呈现的TypesOf实现有效,因为TypesOf<[{value: number}, {value: string}]>确实评估为[number, string]。数组和元组上的映射类型产生数组和元组。

但是有一个问题,在microsoft/TypeScript#27995中报告,编译器没有意识到在映射类型实现{[I in keyof T]: ...T[I]...}I最终只会成为类似数字的索引。它认为I可能是"push""pop"之类的东西,因此T[I]不能被认为是Argument:

类型
export type TypesOf<T extends Argument[]> =
{ [I in keyof T]: T[I]["value"] };
// -----------------> ~~~~~~~~~~~~~
// Type '"value"' cannot be used to index type 'T[I]'.

大概这就是你问这个问题的原因吧。GitHub问题被列为一个bug,但它已经开放了很长时间,不清楚这里是否会发生任何事情。


在这种情况下,我倾向于使用Extract<T, U>实用程序类型来帮助说服编译器某些类型将可分配给另一个类型。如果知道类型T可以赋值给U,但编译器不知道,则可以使用Extract<T, U>代替T。当稍后指定T时,如果您对可分配性的判断是正确的,那么Extract<T, U>将只计算为TExtract<T, U>将被编译器视为可赋值给TU

在本例中,我们知道T[I]可以赋值给Argument,但编译器不知道。因此,以下使用Extract<T[I], Argument>的解决方案将在不影响TypesOf输出的情况下抑制编译器错误:

export type TypesOf<T extends Argument[]> =
{ [I in keyof T]: Extract<T[I], Argument>["value"] }; // no error
type Z = TypesOf<[{ value: number }, { value: string }]>;
// type Z = [number, string]

看起来不错!

Playground链接到代码

相关内容

  • 没有找到相关文章

最新更新