我有一个更复杂问题的简化版本。以下情况会导致 TSC 抛出错误:
type Demo<isTrue> = isTrue extends true ? { a: string } : isTrue extends false ? { b: string } : never;
const func = <T extends boolean>(arg: T): Demo<T> => {
if (arg) {
return {a: "hello" };
} else {
return { b: "world" };
}
};
const out = func(true);
抛出以下错误:
Type '{ a: string; }' is not assignable to type 'Demo<T>'.
Type '{ b: string; }' is not assignable to type 'Demo<T>'.
底部的 out
经检查具有正确的类型,因此只有函数定义存在问题。我怎样才能更好地理解这个问题以及如何解决它?
最佳答案
How can I understand this better?
看看this GitHub thread (另请参阅 original issue )。归根结底,TypeScript 在使用条件类型时不支持缩小函数返回类型。自Demo
决议以来类型取决于泛型类型参数 T
,这和直接在返回类型注解中写条件是一样的。
如果我们重写Demo
,问题应该会变得更清楚。类型(仅用于演示目的):
type D<T extends boolean> = {
true: {
a: string
},
false: {
b: string
}
}[`${T}`];
const func = <T extends boolean>(arg: T): D<T> => {
if (arg) {
return {a: "hello" }; //Type '{ a: string; }' is not assignable to type '{ a: string; } & { b: string; }'
} else {
return { b: "world" }; //Type '{ b: string; }' is not assignable to type '{ a: string; } & { b: string; }'
}
};
现在应该很清楚 D<T>
直到您为类型形参提供实参为止,该问题仍然无法解决。这就是为什么const out = func(true);
推断正确。
How do I solve it?
您几乎只能使用类型断言,如 as Demo<T>
或者删除泛型类型参数并使用重载重写签名,如 captain-yossarian's 中所述。回答。
关于Typescript 函数输出无法分配给条件类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66310189/