【发布时间】:2022-01-12 07:18:35
【问题描述】:
我需要一个映射类型来表示一个对象,其中属性是可选的 RxJS Observables。
实现这一目标的最简单和最简单的方法是使用这种类型:
type OptionalObservables<T> = {
[K in keyof T]: T[K] | Observable<T[K]>
}
可以这样使用:
const animal: OptionalObservables<Animal> = {
species: 'dog',
noise: of('bark') // RxJS Observable that satisfies Observable<string>
}
(我有一个单独的函数来解析一个对象并订阅 observables。但这个问题并不是关于它的 RxJS 方面。)
但是...对于可观察对象,我通常更喜欢使用 $ 后缀约定,所以我真正想要的是在选择可观察对象时,我希望在键的末尾有一个 $。 Key Remapping 可以进行这样的操作。
{
species: 'dog',
noise$: of('bark')
}
事实证明,让所有东西协同工作比我预期的要困难得多!
对于OptionalObservables<{ species: string, noise: string }>,我最终需要的最终类型是:
// species as a string or observable
({ species: string } | { species$: Observable<string> }) &
// noise as a string or observable
({ noise: string } | { noise$: Observable<string> })
(其中 T 的每个属性 K 都是必需的,并且可以是 T[K] 或 Observable
我最接近的基础是这样的:
type OptionalObservables<T> =
{
[K in keyof T]: K extends string ?
// the original property name and type
{ [P in K]: T[K] }
|
// OR the original property name with $ suffix and Observable type
{ [P in `${K}\$`]: Observable<T[K]> }
: never
}
这增加了一个额外的“嵌套”级别(但在其他方面满足了我的要求)所以我最终得到了这个:
{
species: {
species: "cat" | "dog";
} |
{
species$: Observable<"cat" | "dog">;
};
noise: {
noise: "bark" | "meow";
} |
{
noise$: Observable<"bark" | "meow">;
};
}
我希望走到这一步可以让我使用Unionize 之类的东西来提取值并将它们合并在一起而无需额外的级别。到目前为止,我只设法获得所有可能的属性是必需的或全部是可选的!
如果有一个我遗漏的技巧或不可能的技巧 - 但希望能够让它发挥作用。
另一种方法可能是验证结构是否与方法兼容,而不是仅依赖于映射类型。
【问题讨论】: