gpt4 book ai didi

javascript - typescript 类型 : array of T to map

转载 作者:行者123 更新时间:2023-11-30 14:07:43 32 4
gpt4 key购买 nike

假设我们有一个类型 T:

type T = {
type: string,
}

和一个接受T数组并返回一个对象的函数,该对象的键是每个T.type的值,其值为T

const toMap = (...args: T[]) => args.reduce((res, t) => ({
...res,
[t.type]: t
}), {});

所以,对于这个给定的例子:

const a = { type: 'hello' };
const b = { type: 'world' };
const c = { type: 'foo' };

const map = toMap(a, b, c);

我期待这个结果

{
hello: { type: 'hello' },
world: { type: 'world' },
foo: { type: 'foo' },
}

map.hello // correct, { type: 'hello' };

// If I access an unknown property, then the compiler should:
map.bar // `property bar doesn't exist on type { hello: { ... }, world: {...}, foo: {...} }`

如何为这个函数编写类型?

最佳答案

您可以先制作 T非常通用:

function toMap<T extends { type: string }>(...args: T[]): { [type: string]: T } {
return args.reduce((res, t) => ({
...res,
[t.type]: t
}), {});
}

为了能够真正缩小类型的范围,您必须为变量参数键入通用类型,例如toMap<A>(arg1: A) , toMap<A, B>(arg1: A, arg2: B) .

不过有两个缺点:

1) 您必须为任意数量的参数创建这些重载, 然而这在 Typescript 中很常见(参见 Object.assign 声明)。

2) typescript 类型 { type: "test" }作为{ type: string }默认情况下(在 99% 的情况下都需要),但是因此我们无法将键类型推断为 "test"直接地。为了解决这个问题,我们必须将字符串文字类型转换为缩小的字符串类型 { type: "test" as "test" } .

// generic overload for one argument
function toMap<A>(arg: A): { [K1 in O<A>]: A };

// generic overload for two arguments:
function toMap<A, B>(arg: A, arg2: B): { [K in O<A>]: A } & { [K in O<B>]: B };

// generic overload for three arguments:
function toMap<A, B, C>(arg: A, arg2: B, arg3: C): { [K in O<A>]: A } & { [K in O<B>]: B } & { [K in O<C>]: C };

// ... repeat for more arguments

// implementation for all kind of args
function toMap<T extends { type: string }>(...args: T[]): { [type: string]: T } {
return args.reduce((res, t) => ({
...res,
[t.type]: t
}), {});
}

// Infers the type of "type", which has to be a string, from a given object
type O<V> = V extends { type: infer K } ? K extends string ? K : never : never;

// Narrow down a.type to be "test" instead of string
const a = { type: "test" as "test" }
const b = { type: "test2" as "test2", v: 1 };

const test = toMap(a);
const test2 = toMap(a, b);

console.log(
test2.test2.v, // works!
test2.whatever, // doesnt!
test2.test2.k // doesnt!
);

Try it!

关于javascript - typescript 类型 : array of T to map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55086835/

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