映射类型的交集 [英] Intersection of mapped types
问题描述
请考虑以下内容:
type Properties = {
foo: { n: number };
bar: { s: string };
baz: { b: boolean };
};
declare function retrieveValues<K extends keyof Properties>(add?: K[]): Pick<Properties, K>[K];
// what happens
const x: { n: number } | { s: string } = retrieveValues(['foo', 'bar']);
// what I'm really trying to express (type error)
const y: { n: number } & { s: string } = retrieveValues(['foo', 'bar']);
有没有办法得到Pick<Properties, K>
属性的交集?或者只是一种不同的方式来根据数组中相关字符串的存在来获取一组类型的交集?
Is there a way to get an intersection of the properties of Pick<Properties, K>
? Or just a different way to get the intersection of a set of types based on the presence of relevant strings in an array?
推荐答案
没有简单的类型运算符,例如,它可以将联合变成交集,或者允许您
There's no straightforward type operator which, say, turns a union into an intersection, or allows you to iterate union types and do stuff programmatically with the pieces. So on the face of it you're stuck.
备份,如果允许您自己从片段中构建Properties
而不是试图将片段分开,则可以执行以下操作:
Backing up, if you allow yourself to build Properties
from pieces instead of trying to break the pieces apart, you can do this:
type InnerProperties = {
n: number;
s: string;
b: boolean;
}
type OuterProperties = {
foo: "n";
bar: "s";
baz: "b";
}
您可以看到OuterProperties
中的每个键如何映射到InnerProperties
中的键. (请注意,在您的Properties
中,每个外部属性都有一个内部属性.不过,您不受此限制.例如,如果想让"foo"
外键对应于具有多个内部属性的内容,例如{n: number, r: RegExp}
,然后将r: RegExp
添加到InnerProperties
并将foo: "n"|"r"
放入OuterProperties
.)
You can see how each key in OuterProperties
is a mapping to a key in InnerProperties
. (Note that in your Properties
, each outer property had a single inner property. You aren't restricted to that, though. If you wanted, say, the "foo"
outer key to correspond to something with multiple inner properties like {n: number, r: RegExp}
then you would add r: RegExp
to InnerProperties
and put foo: "n"|"r"
in OuterProperties
.)
现在,您可以像这样选择部分属性:
Now you can pick out partial properties like this:
type PickProps<P extends keyof OuterProperties = keyof OuterProperties> = {
[K in OuterProperties[P]]: InnerProperties[K];
}
所以PickProps<"foo">
是{n: number}
,并且PickProps<"bar">
是{s: string}
,并且PickProps<"baz">
是{b: boolean}
.并注意PickProps<"foo"|"bar">
是{n: number; s: string}
,因此我们已经准备好了retrieveValues()
的输出类型.我们仍然必须根据InnerProperties
和OuterProperties
来定义Properties
,如下所示:
So PickProps<"foo">
is {n: number}
, and PickProps<"bar">
is {s: string}
, and PickProps<"baz">
is {b: boolean}
. And notice that PickProps<"foo"|"bar">
is {n: number; s: string}
, so we have the output type of retrieveValues()
ready. We still have to define Properties
in terms of InnerProperties
and OuterProperties
, like this:
type Properties = {
[K in keyof OuterProperties]: PickProps<K>
}
最后,您可以按照自己的方式声明该函数:
And finally you can declare that function the way you want it:
declare function retrieveValues<K extends keyof Properties>(add?: K[]): PickProps<K>;
const y: { n: number } & { s: string } = retrieveValues(['foo', 'bar']);
这样行得通.希望对您有所帮助.祝你好运!
So that works. Hope that's helpful. Good luck!
这篇关于映射类型的交集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!