[英]How to derive an object type with another object's values in Typescript?
I'm trying to create a function that will return a generic object type with keys that are derived from an argument passed into that function.我正在尝试创建一个函数,该函数将返回一个通用对象类型,其键是从传递给该函数的参数派生的。 A simplified example:
一个简化的例子:
// What do I put here for this to work?
type ObjectB<T> = {};
declare function makeObjectB<T>(a: T): ObjectB<T>;
const objectB = makeObjectB({
name: "foo"
});
console.log(objectB.foo)
typeof objectB
would result in something like: typeof objectB
会导致类似:
{
foo: string
}
Bonus points if the following example could also be supported:如果还支持以下示例,则加分:
// What do I put here for this to work?
type ObjectB<T> = {};
declare function makeObjectB<T>(a: T[]): ObjectB<T[]>;
const objectB = makeObjectB([{ name: "foo" }, { name: "bar" }]);
console.log(objectB.foo)
console.log(objectB.bar)
typeof objectB => { foo: string; bar: string }
Sure it is, with a mapped type:当然可以,使用映射类型:
type ObjectB<T extends { name: string }> = {
[K in T["name"]]: string;
};
You will notice the extends { name: string }
after T
.您会注意到
T
之后的extends { name: string }
。 This is a generic constraint, which is similar to a function parameter type argument.这是一个通用约束,类似于函数参数类型参数。
Inside the mapped type, we go through each K
in T["name"]
and map it to a string
.在映射类型中,我们遍历
T["name"]
中的每个K
并将其映射到string
。
So if we had this: ObjectB<{ name: "foo" }>
, T["name"]
would be "foo"
and this type would result in:因此,如果我们有这个:
ObjectB<{ name: "foo" }>
, T["name"]
将是"foo"
并且这种类型将导致:
{
foo: string;
}
With this type, we can write our function signature now:使用这种类型,我们现在可以编写函数签名:
declare function makeObjectB<T extends { name: string }>(a: T): ObjectB<T>;
You will also notice that the same generic constraint is present here.您还会注意到这里存在相同的通用约束。 This is to satisfy TypeScript that
T
from makeObjectB
can be used with ObjectB
.这是为了满足 TypeScript 的要求,即
makeObjectB
中的T
可以与ObjectB
一起使用。
And for bonus points, we can define an overload:对于奖励积分,我们可以定义一个重载:
declare function makeObjectB<T extends ReadonlyArray<{ name: string }>>(a: T): ObjectB<T[number]>;
T
can now be any array of objects that have a name
key that points to a string. T
现在可以是具有指向字符串的name
键的任何对象数组。
The other thing that's different here is using ObjectB<T[number]>
instead of just ObjectB<T>
.这里不同的另一件事是使用
ObjectB<T[number]>
而不仅仅是ObjectB<T>
。 This lets us get all the elements in the array (technically tuple here) as a union, which means T["name"]
is now something like "foo" | "bar"
这让我们可以将数组中的所有元素(此处为元组)作为一个联合,这意味着
T["name"]
现在类似于"foo" | "bar"
"foo" | "bar"
. "foo" | "bar"
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.