簡體   English   中英

通過 object 屬性推斷條件返回泛型類型

[英]Infer conditional return generic types by object property

我正在嘗試推斷每個屬性的通用類型Model 當前所有內容都顯示為unknown[]而不是下面評論中所需的類型。

操場

 class Model<T> { x?: T } type ArgumentType<T> = T extends Model<infer TInner>? Model<TInner>: ( T extends Model<infer TInner>[]? Model<TInner>[]: never ); type ReturnType<T> = T extends Model<infer TInner>? TInner[]: ( T extends Model<infer TInner>[]? TInner[][]: never ); const test = <TInner, TValue extends ArgumentType<TInner>, T extends Record<string, TValue>>(models: T): Record<keyof T, ReturnType<TValue>> => { return; } const numberModel = new Model<number>(); const stringModel = new Model<string>(); const bigintModel = new Model<bigint>(); const result = test({ prop1: [numberModel, numberModel, numberModel], prop2: [stringModel], prop3: stringModel, prop4: [numberModel, numberModel, numberModel, bigintModel], prop5: stringModel }); //expected types result.prop1 // number[][] result.prop2 // string[][] result.prop3 // string[] result.prop4 // (number | bigint)[][] result.prop5 // string[] //actual types result.prop1 // unknown[] result.prop2 // unknown[] result.prop3 // unknown[] result.prop4 // unknown[] result.prop5 // unknown[]

我對你的test() function 的建議是給它以下調用簽名:

declare const test: <T extends Record<keyof T, Model<any> | Model<any>[]>>(
  models: T
) => { [K in keyof T]:
    T[K] extends Model<infer U> ? U[] :
    T[K] extends Model<infer U>[] ? U[][] :
    never
  }

請注意,我們只有一個泛型類型參數T ,與為models function 參數傳入的類型完全對應。 T限制Record<keyof T, Model<any> | Model<any>[]> Record<keyof T, Model<any> | Model<any>[]> ,這意味着它可以有任何鍵,但它的屬性值必須全部是某個 X 的Model<X>或某個XModel<X> X 這是一個相當直接和具體的約束。

在您的原始版本中,您有三個類型參數,每個參數都被限制為另一個類型的某種類型 function,但是 TypeScript 的編譯器無法以這種方式進行推理。 如果你有類型參數U, V extends F<U>, W extends F<V>如果你給編譯器一個U類型的值,你可能會得到推斷,但是如果你只給編譯器一個類型W的值。 它不能向后運行引擎來讓WV做某事,然后讓VU做某事。 使用單個類型參數要容易得多。

然后注意 output 類型

{ [K in keyof T]:
    T[K] extends Model<infer U> ? U[] :
    T[K] extends Model<infer U>[] ? U[][] :
    never
}

本質上是您的( 不幸命名的) ReturnType<>類型別名,但映射到T的屬性上。 對於對應於models的類型T中的每個屬性鍵K ,我們采用屬性值類型T[K]並執行類似於您的ReturnType<T[K]>的操作。


讓我們測試一下:

const numberModel = new Model<number>();
const stringModel = new Model<string>();
const bigintModel = new Model<bigint>();

const result = test({
  prop1: [numberModel, numberModel, numberModel],
  prop2: [stringModel],
  prop3: stringModel,
  prop4: [numberModel, numberModel, numberModel, bigintModel],
  prop5: stringModel
});

/* const result: {
    prop1: number[][];
    prop2: string[][];
    prop3: string[];
    prop4: (number | bigint)[][];
    prop5: string[];
} */

看起來挺好的!

游樂場代碼鏈接

暫無
暫無

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

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