簡體   English   中英

如何在 TypeScript 的這個復雜類型定義中提取泛型類型?

[英]How to extract generic type in this complex type definition in TypeScript?

https://stackblitz.com/edit/xh93ag?file=index.ts

考慮我有這些類型

type TDomainConditionOperator =
    '=' | '!=' | '>' | '>=' | '<' | '<=' | '=?' |
    '=like' | 'like' | 'not like' | 'ilike' | 'not ilike' | '=ilike' |
    'in' | 'not in' | 'child_of' | 'parent_of'
    ;
type TDomainCondition = [string, TDomainConditionOperator, any];
export type TDomain = TDomainCondition | '|' | '&' | '!';

export type TReferenceValue<T, TypeOnly extends boolean = false> = TypeOnly extends true ?
    T :
    T | number | Upsert<T>;

export type TToOne<T, TypeOnly extends boolean = false> = TypeOnly extends true ?
    TReferenceValue<T, TypeOnly> :
    TReferenceValue<T, TypeOnly> | Domains;

export type TToMany<T, TypeOnly extends boolean = false> = TypeOnly extends true ?
    Array<TReferenceValue<T, TypeOnly>> :
    Array<TReferenceValue<T, TypeOnly>> | Domains | ToManyCommands;

class Domains {}
class ToManyCommands {}
class Upsert<T> {}

我創建了這種類型來從TToManyTToOne中提取T

export type ExtractOdooRelation<T> = (
        T extends TToMany<infer S> ?
            (
                Exclude<S, Domains | ToManyCommands> extends Array<infer S1> ?
                    S1 : 1
            ) : (
                T extends TToOne<infer R> ?
                    Exclude<R, Domains> : 2
            )
    ) extends TReferenceValue<infer R1, boolean> ?
        Exclude<R1, number | Upsert<T>> : 3
;

但是它沒有按預期工作。

class StockMove {}

// I expect it resolves as type  StockMove but not never
const whyIsThisType_Never: ExtractOdooRelation<TToMany<StockMove, false>>;

什么似乎遺漏或錯誤?


我的目標是編寫一種用於自動完成下面的 object 結構的類型

    class ResPartner {
        name: string;
    }

    class ResGroup {
        name: string;
    }

    class ProductProduct {
        name: string;
    }

    class StockMove {
        group_id: TToOne<ResGroup>;
        product_id: TToOne<ProductProduct>;
        partner_id: TToOne<ResPartner>;
    }

    class StockPicking {
        move_lines: TToMany<StockMove>;
    }


    // Developer should have Typescript type checking and autocomplete backed for writing this object
    await stockPickingFactory.deep_search_read<StockPicking>({
        move_lines: {
            read: ['group_id', 'product_id'],
            preload: {
                company_id: {
                    read: ['partner_id'],
                    preload: {
                        partner_id: {}
                    }
                },
            }
        }
    });

正確的類型是

export type ExtractOdooRelation<T> =
    (
        T extends TToMany<infer S> ? (
            Exclude<T, Domains | ToManyCommands>
        ) : (
            T extends TToOne<infer S> ?
                Exclude<S, Domains> : never
        )
        // It is a bit weird that need to first infer R before infer Q in Array for TToMany
    ) extends TReferenceValue<infer R> ? (
        R extends Array<infer Q> ?
            Exclude<Q, number | Upsert<Q>> :
            Exclude<R, number | Upsert<R>>
    ) : never
;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM