如何创建需要设置单个属性的Partial-like [英] How to create a Partial-like that requires a single property to be set
问题描述
出口类型LinkRestSource = {
model:string;
rel ?: string;
title?:string;
} | {
model?:string;
rel:string;
title?:string;
} | {
model?:string;
rel ?: string;
title:string;
};
这与说法几乎相同
type LinkRestSource =部分< {model:string,rel:string,title:string}>
除了这将允许空对象被传入,而初始类型需要其中一个属性在
中传递如何创建类似于部分
的泛型,但其行为与上面的结构相似?
我想我有一个适合您的解决方案。您正在寻找一些类型为 T
的东西,并生成一个相关类型,其中至少包含 属性<部分< T>
,但不包括空对象。
type AtLeastOne
解析它:首先, AtLeastOne< T>
为部分< T>
与 相交。 U [keyof U]
表示它是 U
的所有属性值的联合。我已经定义(默认值) U
为映射类型,其中 T
的每个属性映射到 Pick< T ,K>
,这是键 K
的单一属性类型。 (例如, Pick< {foo:string,bar:number},'foo'>
相当于 {foo:string}
...它从原始类型中挑选'foo'
属性。)含义 U [keyof U]
在这种情况下是来自 T
的所有可能的单一财产类型的联合。
嗯,这可能会让人困惑。让我们一步步看看它是如何在以下具体类型上运行的:
类型FullLinkRestSource = {
model:串;
rel:string;
title:string;
}
type LinkRestSource = AtLeastOne< FullLinkRestSource>
扩展为
type LinkRestSource = AtLeastOne< FullLinkRestSource,{
[Key in FullFRestSource]中的K:Pick< FullLinkRestSource,K>
}>
或
type LinkRestSource = AtLeastOne< FullLinkRestSource,{
model:Pick< FullLinkRestSource,'model'> ;,
rel:Pick< FullLinkRestSource,'rel'> ;,
title:选择< FullLinkRestSource,'标题'>
}>
或
type LinkRestSource = AtLeastOne< FullLinkRestSource,{
model:{model:string},
rel:{rel:string},
title:{title:string}>
}>
或
type LinkRestSource =部分< FullLinkRestSource> &安培; {
模型:{model:string},
rel:{rel:string},
title:{title:string}>
} [keyof {
model:{model:string},
rel:{rel:string},
title:{title:string}>
}]
或
type LinkRestSource =部分< FullLinkRestSource> &安培; {
模型:{model:string},
rel:{rel:string},
title:{title:string}>
} ['model'| 'rel'| 'title']
或
type LinkRestSource =部分< FullLinkRestSource> &安培;
({model:string} | {rel:string} | {title:string})
或
type LinkRestSource = {model ?: string,rel ?: string,title ?: string}&
({model:string} | {rel:string} | {title:string})
或
type LinkRestSource = {model:string,rel ?: string,title ?: string}
| {model?:string,rel:string,title?:string}
| {model?:string,rel?:string,title:string}
你可以测试它:
const okay0:LinkRestSource = {model:'a',rel:'b',title:'c'}
const okay1:LinkRestSource = {model:'a',rel:'b'}
const okay2:LinkRestSource = {model:'a'}
const okay3:LinkRestSource = {rel:'b'}
const okay4:LinkRestSource = {title:'c'}
const error0:LinkRestSource = {//缺少属性
const错误1:LinkRestSource = {model:'a',titel:'c'} //字符串文字的额外属性
那么,这对你有用吗?祝你好运!
We have structure that is like the following:
export type LinkRestSource = {
model: string;
rel?: string;
title?: string;
} | {
model?: string;
rel: string;
title?: string;
} | {
model?: string;
rel?: string;
title: string;
};
Which is almost the same as saying
type LinkRestSource = Partial<{model: string, rel: string, title: string}>
Except that this will allow an empty object to be passed in whereas the initial type requires one of the properties to be passed in
How can I create a generic like Partial
, but that behaves like my structure above?
I think I have a solution for you. You're looking for something that takes a type T
and produces a related type which contains at least one property from T
. That is, it's like Partial<T>
but excludes the empty object.
If so, here it is:
type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
To dissect it: first of all, AtLeastOne<T>
is Partial<T>
intersected with something. U[keyof U]
means that it's the union of all property values of U
. And I've defined (the default value of) U
to be a mapped type where each property of T
is mapped to Pick<T, K>
, a single-property type for the key K
. (For example, Pick<{foo: string, bar: number},'foo'>
is equivalent to {foo: string}
... it "picks" the 'foo'
property from the original type.) Meaning that U[keyof U]
in this case is the union of all possible single-property types from T
.
Hmm, that might be confusing. Let's see step-by-step how it operates on the following concrete type:
type FullLinkRestSource = {
model: string;
rel: string;
title: string;
}
type LinkRestSource = AtLeastOne<FullLinkRestSource>
That expands to
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
[K in keyof FullLinkRestSource]: Pick<FullLinkRestSource, K>
}>
or
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
model: Pick<FullLinkRestSource, 'model'>,
rel: Pick<FullLinkRestSource, 'rel'>,
title: Pick<FullLinkRestSource, 'title'>
}>
or
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}>
or
type LinkRestSource = Partial<FullLinkRestSource> & {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}[keyof {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}]
or
type LinkRestSource = Partial<FullLinkRestSource> & {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}['model' | 'rel' | 'title']
or
type LinkRestSource = Partial<FullLinkRestSource> &
({model: string} | {rel: string} | {title: string})
or
type LinkRestSource = {model?: string, rel?: string, title?: string} &
({model: string} | {rel: string} | {title: string})
or
type LinkRestSource = { model: string, rel?: string, title?: string }
| {model?: string, rel: string, title?: string}
| {model?: string, rel?: string, title: string}
which is, I think, what you want.
You can test it out:
const okay0: LinkRestSource = { model: 'a', rel: 'b', title: 'c' }
const okay1: LinkRestSource = { model: 'a', rel: 'b' }
const okay2: LinkRestSource = { model: 'a' }
const okay3: LinkRestSource = { rel: 'b' }
const okay4: LinkRestSource = { title: 'c' }
const error0: LinkRestSource = {} // missing property
const error1: LinkRestSource = { model: 'a', titel: 'c' } // excess property on string literal
So, does that work for you? Good luck!
这篇关于如何创建需要设置单个属性的Partial-like的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!