typescript - Issues with generic type narrowing on merged records - Stack Overflow
I know that the following example might be a little specific, however, I was not able to generalize it further. I would appreciate if you could help me narrow down the issue and I'd be happy to update the question afterwards.
In my apps, I often create class
wrappers for API data. I would like to be able to make some of these models generic and add more embedded properties to them. For example, there might be a ProductModel
, which extends the base ApiModel
, and then I would like to create a B2BProductModel
, which extends the ProductModel
and has some extra properties.
I pass the embedded property types through a generic:
class Model<TEmbeds extends Record<string, any> = {}> {
and then access them through the following method:
getEmbed<K extends keyof TEmbeds>(key: K): TEmbeds[K];
getEmbed<K extends keyof TEmbeds, M extends ConstructorType<Model>>(
key: K,
model: M
): TEmbeds[K] extends any[]
? InstanceType<M>[]
: TEmbeds[K] extends Record<any, InstanceType<M>>
? Record<keyof TEmbeds[K], InstanceType<M>>
: InstanceType<M> | null
getEmbed<K extends keyof TEmbeds, M extends ConstructorType<Model>>(
key: K,
model?: M
): TEmbeds[K] | InstanceType<M>[] | Record<keyof TEmbeds[K], InstanceType<M>> | InstanceType<M> | null {
The issue I ran into, though, is that when I want to extend the type of TEmbeds
, the getEmbed
method doesn't narrow down the type and instead, returns a union of all the possible types.
interface Embeds {
baz: SomeModel[]
}
type DisallowObjectProps<T extends Record<string, any>> = Partial<{ [key in keyof T]: never }>
type MergeLeft<A extends Record<string, any>, B> = B extends Record<string, any> ? {
[K in keyof A | keyof B]: K extends keyof A ? A[K] : K extends keyof B ? B[K] : never
} : A
class FooModel<
TExtraEmbeds extends Record<string, any> & DisallowObjectProps<Embeds>,
> extends Model<
MergeLeft<Embeds, TExtraEmbeds>
> {
get baz() {
// Issue: the type is not SomeModel[], but rather: SomeModel | SomeModel[] | Record<keyof MergeLeft<Embeds, TExtraEmbeds>["baz"], SomeModel> | null
return this.getEmbed('baz', SomeModel);
}
processBaz() {
return this.baz.map((item) => item.doSomething()); // <----
}
}
How could I fix this, please? Here is the TS Playground link: /mZ3aeW
- 谷歌继续封死华为后路,Mate 30无法安装谷歌服务
- 有点厉害 win10兼容安卓应用方式曝光
- 微信支付和支付宝口水战开打!
- Windows8是备胎?解析微软移动市场战略
- 惠普CEO惠特曼访华:我们不走IBM之路
- python - tensorflow-gpu installation failed in colab - Stack Overflow
- scipy - Generalized Nonsymmetric Eigensolver Python - Stack Overflow
- verilog - Is it possible to create task within interface for specific modport? - Stack Overflow
- reactjs - How to change output directory of wxt extension framework - Stack Overflow
- javascript - AJAX implementation doesn't work properly for "like" button ASP.NET Core 2.1 - Stack Over
- tensorflow - Error when loading old .h5 file with latest Keras - Stack Overflow
- c++ - Wrong Precision Results with std::ostringstream - Stack Overflow
- c - Segmentation fault when access mapped memory - Stack Overflow
- javascript - How to play HLS live-stream from the end with Bitmovin player - Stack Overflow
- css - How can I apply a view-transition to my sidebar only? - Stack Overflow
- c++ - Why does changing the thread language and back fail for known folders? - Stack Overflow
- typescript - angular signal is not recomputing - Stack Overflow