[英]Typescript Generic to map an array of const objects to a list of types
I have some JSON data that I've strongly typed with an as const
assertion.我有一些 JSON 数据,我用as const
断言强类型化了这些数据。
const myList = [
{ type: 'uint256'},
{ type: 'address'}
] as const;
Now I want to convert this to the following tuple type:现在我想将其转换为以下元组类型:
[number, string]
Basically, if the type is "address" it should resolve to string
.基本上,如果类型是“地址”,它应该解析为string
。
If the type is a "uint256", it should resolve to number
.如果类型是“uint256”,它应该解析为number
。
I intend to use this type to create arrays of data that conform to this schema, eg:我打算使用这种类型来创建 arrays 符合这种模式的数据,例如:
const foo: ConvertToTuple<typeof myList> = [1, 'asdf'];
I'm struggling to write a generic that can do this.我正在努力编写一个可以做到这一点的泛型。 Here's where I'm at so far:到目前为止,这是我所在的位置:
type ConvertToTuple<
DataObjects extends readonly { type: "address" | "uint256" }[]
> = DataObjects extends readonly [infer CurrentObject, ...infer RestObjects]
? CurrentObject["type"] extends "address"
? [string, ...ConvertToTuple<RestObjects>]
: CurrentObject["type"] extends "uint256"
? [number, ...ConvertToTuple<RestObject>]
: never
: [];
I don't think I'm using infer
correctly here.我认为我在这里没有正确使用infer
。 Typescript is throwing a couple of errors: Typescript 抛出几个错误:
Type '"type"' cannot be used to index type 'CurrentObject'
and和
Type 'RestObjects' does not satisfy the constraint 'readonly { type: "address" | "uint256"; }[]'.
Type 'unknown[]' is not assignable to type 'readonly { type: "address" | "uint256"; }[]'.
Type 'unknown' is not assignable to type '{ type: "address" | "uint256"; }'.
Any help untangling this is much appreciated!非常感谢任何帮助解决这个问题的帮助!
TypeScript added extends
constraints on infer
type variables in version 4.7, so you can simplify the recursive mapped type utility like this: TypeScript 在版本 4.7 中添加了对infer
类型变量的extends
约束,因此您可以像这样简化递归映射类型实用程序:
type ListType = "address" | "uint256";
type ListElement = { type: ListType };
type Transform<Tup extends readonly ListElement[]> =
Tup extends readonly [
infer H extends ListElement,
...infer R extends readonly ListElement[]
]
? [
H["type"] extends "address" ? string : number,
...Transform<R>
]
: Tup;
const myList = [
{ type: "uint256" },
{ type: "address" },
] as const satisfies readonly ListElement[];
type Foo = Transform<typeof myList>;
//^? type Foo = [number, string]
const foo: Foo = [1, "asdf"]; // ok
If your enumeration of possible string literal types ends up growing, you can also use a type mapping of string literals to their corresponding types like this:如果您对可能的字符串文字类型的枚举最终增加,您还可以使用字符串文字到它们相应类型的类型映射,如下所示:
type TransformTypeMap = {
address: string;
uint256: number;
};
type Transform<Tup extends readonly ListElement[]> =
Tup extends readonly [
infer H extends ListElement,
...infer R extends readonly ListElement[]
]
? [TransformTypeMap[H["type"]], ...Transform<R>]
: Tup;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.