Jua*_*des 16 generics typescript
我们的结构如下:
export type LinkRestSource = {
model: string;
rel?: string;
title?: string;
} | {
model?: string;
rel: string;
title?: string;
} | {
model?: string;
rel?: string;
title: string;
};
Run Code Online (Sandbox Code Playgroud)
这几乎与说法相同
type LinkRestSource = Partial<{model: string, rel: string, title: string}>
Run Code Online (Sandbox Code Playgroud)
除了这将允许传入空对象,而初始类型需要传递其中一个属性
我怎样才能创建类似的泛型Partial
,但其行为与上面的结构相似?
jca*_*alz 31
我想我有一个解决方案.你正在寻找一种类型T
并生成相关类型的东西,其中包含至少一个属性T
.也就是说,它就像是Partial<T>
排除了空物体.
如果是这样,这里是:
type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
Run Code Online (Sandbox Code Playgroud)
要对它进行解剖:首先AtLeastOne<T>
是Partial<T>
交叉的东西. U[keyof U]
意味着它是所有属性值的并集U
.和我定义(默认值)U
是一个映射类型,其中的每个属性T
被映射到Pick<T, K>
,单属性类型的关键K
.(例如,Pick<{foo: string, bar: number},'foo'>
相当于{foo: string}
......它'foo'
从原始类型中"选取" 属性.)这意味着U[keyof U]
在这种情况下是所有可能的单属性类型的并集T
.
嗯,这可能会令人困惑.让我们一步一步地看看它如何在以下具体类型上运行:
type FullLinkRestSource = {
model: string;
rel: string;
title: string;
}
type LinkRestSource = AtLeastOne<FullLinkRestSource>
Run Code Online (Sandbox Code Playgroud)
这扩大到了
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
[K in keyof FullLinkRestSource]: Pick<FullLinkRestSource, K>
}>
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
model: Pick<FullLinkRestSource, 'model'>,
rel: Pick<FullLinkRestSource, 'rel'>,
title: Pick<FullLinkRestSource, 'title'>
}>
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = AtLeastOne<FullLinkRestSource, {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}>
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = Partial<FullLinkRestSource> & {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}[keyof {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}]
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = Partial<FullLinkRestSource> & {
model: {model: string},
rel: {rel: string},
title: {title: string}>
}['model' | 'rel' | 'title']
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = Partial<FullLinkRestSource> &
({model: string} | {rel: string} | {title: string})
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = {model?: string, rel?: string, title?: string} &
({model: string} | {rel: string} | {title: string})
Run Code Online (Sandbox Code Playgroud)
要么
type LinkRestSource = { model: string, rel?: string, title?: string }
| {model?: string, rel: string, title?: string}
| {model?: string, rel?: string, title: string}
Run Code Online (Sandbox Code Playgroud)
我认为,这就是你想要的.
你可以测试一下:
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
Run Code Online (Sandbox Code Playgroud)
那么,这对你有用吗?祝好运!
小智 28
如果您知道想要哪些属性,还有另一种解决方案。
AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>
Run Code Online (Sandbox Code Playgroud)
这也将允许您锁定一个类型的多个键,例如AtLeast<T, 'model' | 'rel'>
.
Gaa*_*far 12
jcalz 提供的更简单的解决方案版本:
type AtLeastOne<T> = { [K in keyof T]: Pick<T, K> }[keyof T]
所以整个实现变成
type FullLinkRestSource = {
model: string;
rel: string;
title: string;
}
type AtLeastOne<T> = { [K in keyof T]: Pick<T, K> }[keyof T]
type LinkRestSource = AtLeastOne<FullLinkRestSource>
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
Run Code Online (Sandbox Code Playgroud)
不幸的是,上述答案对我不起作用。
要么是因为编译器无法捕获错误,要么是因为我的 IDE 无法检索对象的预期属性,即使它的类型已注释。
以下内容完美运行,取自官方microsoft azure/keyvault-certificates 包:
type RequireAtLeastOne<T> = { [K in keyof T]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<keyof T, K>>>; }[keyof T]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4051 次 |
最近记录: |