[英]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>
或某個X
的Model<X>
X
。 這是一個相當直接和具體的約束。
在您的原始版本中,您有三個類型參數,每個參數都被限制為另一個類型的某種類型 function,但是 TypeScript 的編譯器無法以這種方式進行推理。 如果你有類型參數U, V extends F<U>, W extends F<V>
如果你給編譯器一個U
類型的值,你可能會得到推斷,但是如果你只給編譯器一個類型W
的值。 它不能向后運行引擎來讓W
對V
做某事,然后讓V
對U
做某事。 使用單個類型參數要容易得多。
然后注意 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.