gpt4 book ai didi

typescript - 推断 TypeScript 中 Object.fromEntries() 结果的形状

转载 作者:行者123 更新时间:2023-12-02 19:21:01 27 4
gpt4 key购买 nike

我正在尝试为 Object.fromEntries() 编写一个更好的定义,以推断结果对象的实际键和值。我有我认为可行的方法,但显然 infer U 的作用域是我的方法无法找到 U 的。

interface ObjectConstructor {
fromEntries<
K extends PropertyKey,
V,
A extends ReadonlyArray<readonly [K, V]> = ReadonlyArray<readonly [K, V]>
>(array: A): {
[key in A[number][0]]: A[number extends infer U ? U : never][0] extends key ? A[U][1] : never;
};
}

A[U][1] 中的 U 无法访问。

Cannot find name 'U'.

另一个问题是 A[number extends infer U ? U : never][0] extends key 似乎总是评估为 false

如何检索与key关联的数组的索引?我猜测有一些 hacky 类型将数组包装在一个函数中,并检查该函数是否扩展了可以推断索引的东西,但我的最佳尝试没有成功。

type ArrayIdxOf<A extends readonly unknown[], K> =
(((i: keyof A) => A[typeof i]) extends ((i: number & infer U) => A[typeof i] extends K ? typeof i : never) ? (i: U) => U : never) extends
((i: number) => infer U)
? U
: never;

const a1 = ['foo', 'bar'] as const;
type A = ArrayIdxOf<typeof a1, 'foo'>; // type A = unknown

interface ObjectConstructor {
fromEntries<
K extends PropertyKey,
V,
A extends ReadonlyArray<readonly [K, V]> | Array<[K, V]>
>(array: A): {
[key in A[number][0]]: ArrayIdxOf<A, key> extends infer I ? I extends number ? A[I][1] : never : never;
};
}

const a2 = [['foo', 'foo'], ['bar', false], [1, 2]] as const;
const x = Object.fromEntries(a2);
/**
* const x: {
* foo: never;
* bar: never;
* 1: never;
* }
*/

如果可能的话,我还想消除 Areadonly 约束。

TS Playground虽然虽然使用 tsc 进行编译,但它不会在 Playground 中编译,所以我不知道它会有多大用处。

最佳答案

我可能会做类似的事情

declare global {
interface ObjectConstructor {
fromEntries<
A extends ReadonlyArray<readonly [PropertyKey, any]>
>(array: A): { [K in A[number][0]]: Extract<A[number], readonly [K, any]>[1] }
}
}

请注意,readonly 不是一个约束,而是一个宽松...string[] 可以分配给 readonly string[],但是反之则不然。通过接受readonly数组,你接受了更多的东西,而不是更少。所以我会保留它们(这很好,因为 as const 往往会产生 readonly 的东西)。

这适用于您的示例:

const x = Object.fromEntries(b);
/* const x: {
foo: "foo";
bar: false;
1: 2;
} */

如果你想给编译器一个提示,它应该尝试将每个元组的第一个元素读取为 literal类型,您可以给它这个修改后的定义:

declare global {
interface ObjectConstructor {
fromEntries<
P extends PropertyKey,
A extends ReadonlyArray<readonly [P, any]>
>(array: A): { [K in A[number][0]]: Extract<A[number], readonly [K, any]>[1] }
}
}

这在您的 as const 版本上的工作方式相同,但如果您直接传递数组文字也将工作:

const c = Object.fromEntries([['foo', 'foo'], ['bar', false], [1, 2]]);
/* const c: {
foo: string;
bar: boolean;
1: number;
} */

您可以稍微调整推论,但基本方法是使用 Extract实用程序类型从数组中提取适当的元组。

无论如何,希望能给你一些指导。祝你好运!

Playground link to code

关于typescript - 推断 TypeScript 中 Object.fromEntries() 结果的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63061180/

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