由于某种原因,即使类型对我来说我仍然会出错:
//* ListWithCards has base of List but contains {cards: Card[]} field
//* ListWithCardsWithCustomFieldValues has base of List but the card type is {cards: CardWithCustomFieldValue[]}
export const recover = (tApi: TrelloRestApi, reportError: CreateErrorReport) => (withException: boolean) => async <
P extends List | ListWithCards | ListWithCardsWithCustomFieldValues | string,
T = P extends string ? List : Exclude<P, 'string'>
>(
param: P
): Promise<T> => {
//* tApi.get.list takes string as an argument and returns List type
//* isString is a typeguard that checks if passed param is string
//* List results in: List | P
const list = isString(param) ? await tApi.get.list(param) : param;
try {
if ('closed' in list && list.closed) {
await tApi.update.list(list.id, { closed: false });
if (withException) await reportError(eTools.listRecovererErrorCard(list));
}
//* error: Spread types may only be created from object types
return { ...list, closed: false };
} catch (error) {
await reportError(error);
//* error: Type 'List | P' is not assignable to type 'T'.
// * Type 'List' is not assignable to type 'T'.
//* 'List' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'List | ListWithCards | ListWithCardsWithCustomFieldValues'
return list;
}
};
我希望在检查param
是否为字符串列表之后,最终会得到:List | ListWithCards | ListWithCardsWithCustomFieldValues
,但在传播时会抱怨list
不是对象,而对象是那一点,或者至少应该这样看。
这也是来自stackblitz的代码示例 https://stackblitz.com/edit/typescript-yyaj4u?file=index.ts
请注意,我在项目中使用的是打字稿3.7.2版本,但即使在具有确定不同版本的stackblitz上,该错误仍然会出现。
答案 0 :(得分:0)
这里有一些冲突。
list
,其类型为P | List
T
是P
,T extends P extends string ? List : Exclude<P, "string">
T
。因此,您不能通过此声明返回类型P | List
,因为T
是P
的子类型。我认为您应该完全省略T
。
export const listRecoverer = (
tApi: TrelloRestApi,
reportError: (error: Error) => Promise<void>
) => (withException: boolean) => async <
P extends List | ListWithCards | ListWithCardsWithCustomFieldValues | string
>(
param: P
): Promise<P | List> => {
const list = isString(param) ? await tApi.get.list(param) : param;
try {
if ("closed" in list && list.closed) {
await tApi.update.list(list.id, { closed: false });
if (withException) await reportError(new Error(""));
}
return { ...list, closed: false };
} catch (error) {
await reportError(error);
// P extends string | List | ListWithCards | ListWithCardsWithCustomFieldValues
// T extends P extends string ? List : Exclude<P, "string">
// const list: P | List
return list;
}
};