[英]In Typescript force generic type parameter to satisfy the type constraints based upon function overload definitions
下面給出了簡化問題的必要代碼框架。 基本上,可以有不同類型的Source
對象。 為簡單起見,下面的代碼中顯示了兩種類型的源: DirectSource
和IndirectSource
。 函數sourceAdapter()
接受Source
和其他幫助程序參數。
在示例中:如果缺少參數key
則Source
必須是DirectSource
; 如果key
是單個字符串值,則Source
必須是IndirectSource
,並且在兩種情況下,代碼都進行必要的調整並返回DirectSource
對象。 如果key
是數組,則Source
應該是IndirectSource
,它也是函數的返回值。
type KeyMap<T> = { [key in keyof T]: number };
type DirectSource = {
value: number;
otherFieldsAndMethods: any;
};
type IndirectSource<T extends object> = {
kvMap: KeyMap<T>;
otherFieldsAndMethods: any;
};
type Source<T extends number | object> = T extends object ? IndirectSource<T> : DirectSource;
// overloads
function sourceAdapter(src: Source<number>): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: keyof T): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: (keyof T)[]): IndirectSource<T>;
function sourceAdapter<T extends number | object>(
src: Source<T>,
key?: keyof T | (keyof T)[]
): T extends object ? IndirectSource<T> : DirectSource {
if (key) { // According to function overloads Source must be an IndirectSource
if (key instanceof Array) { // Config and return IndirectSource
const kvMap = key.reduce((ac, s) => {
ac[s] = (src as any).kvMap[s];
return ac;
}, {} as any);
// ******Error here:
// Type 'T' does not satisfy the constraint 'object'.
let ret: IndirectSource<T> = {
kvMap,
otherFieldsAndMethods: src.otherFieldsAndMethods
};
return ret;
} else { // Config and return DirectSource
let directSource = {
otherFieldsAndMethods: src.otherFieldsAndMethods,
value: (src as IndirectSource<any>).kvMap[key],
};
return directSource; // ******Error here: assignability
}
} else { // Source is a DirectSource, simply return the src.
return src;
}
}
錯誤產生的行標有星號。 這是到游樂場的鏈接。
最簡單的清潔方法就是將ReturnType更改為並集。 請享用。 游樂場鏈接
type KeyMap<T> = { [key in keyof T]: number };
type DirectSource = {
value: number;
otherFieldsAndMethods: any;
};
type IndirectSource<T extends object> = {
kvMap: KeyMap<T>;
otherFieldsAndMethods: any;
};
type Source<T extends number | object> = T extends object ? IndirectSource<T> : DirectSource;
// overloads
function sourceAdapter(src: Source<number>): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: keyof T): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: (keyof T)[]): IndirectSource<T>;
function sourceAdapter<T extends object>(
src: Source<T>,
key?: keyof T | (keyof T)[]
): IndirectSource<T> | DirectSource {
if (key) { // According to function overloads Source must be an IndirectSource
if (key instanceof Array) { // Config and return IndirectSource
const kvMap = key.reduce((ac, s) => {
ac[s] = (src as any).kvMap[s];
return ac;
}, {} as any);
// Error here:
// Type 'T' does not satisfy the constraint 'object'.
let ret: IndirectSource<T> = {
kvMap,
otherFieldsAndMethods: src.otherFieldsAndMethods
};
return ret as IndirectSource<T>;
} else { // Config and return DirectSource
let directSource = {
otherFieldsAndMethods: src.otherFieldsAndMethods,
value: (src as IndirectSource<any>).kvMap[key],
};
return directSource; // Error here: assignability
}
} else { // Source is a DirectSource, simply return the src.
return src;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.