无法将Typescript函数输出分配给条件类型

无法将Typescript函数输出分配给条件类型,typescript,conditional-types,function-signature,Typescript,Conditional Types,Function Signature,我有一个更复杂问题的简化版本。以下情况导致TSC抛出错误: type Demo=isTrue扩展为true?{a:string}:isTrue扩展为false?{b:string}:从不; 常量func=(参数:T):演示=>{ 如果(arg){ 返回{a:“你好”}; }否则{ 返回{b:“世界”}; } }; const out=func(真); 抛出以下错误: 类型“{a:string;}”不能分配给类型“Demo”。 类型“{b:string;}”不可分配给类型“Demo”。 底部的

我有一个更复杂问题的简化版本。以下情况导致TSC抛出错误:

type Demo=isTrue扩展为true?{a:string}:isTrue扩展为false?{b:string}:从不;
常量func=(参数:T):演示=>{
如果(arg){
返回{a:“你好”};
}否则{
返回{b:“世界”};
}
};
const out=func(真);
抛出以下错误:

类型“{a:string;}”不能分配给类型“Demo”。
类型“{b:string;}”不可分配给类型“Demo”。
底部的
out
在检查时具有正确的类型,因此只有函数定义存在问题。我如何更好地理解这一点,如何解决它


我添加了重载和
Demo
作为返回类型

在这种特殊情况下,
T扩展布尔值
实际上与
Demo
相同

但是请记住,泛型是很棘手的<代码>扩展并不意味着
相等

type Demo=isTrue扩展为true?{a:string}:isTrue扩展为false?{b:string}:从不;
函数func(参数:false):演示
函数func(arg:true):演示
函数func(arg:boolean):演示{
如果(arg==true){
常数a=arg;
返回{a:“你好”};
}否则{
返回{b:“世界”};
}
};
const out=func(真);

我添加了重载和
Demo
作为返回类型

在这种特殊情况下,
T扩展布尔值
实际上与
Demo
相同

但是请记住,泛型是很棘手的<代码>扩展并不意味着
相等

type Demo=isTrue扩展为true?{a:string}:isTrue扩展为false?{b:string}:从不;
函数func(参数:false):演示
函数func(arg:true):演示
函数func(arg:boolean):演示{
如果(arg==true){
常数a=arg;
返回{a:“你好”};
}否则{
返回{b:“世界”};
}
};
const out=func(真);

我怎样才能更好地理解这一点

看一看(另请参阅)。归结起来,TypeScript在使用条件类型时不支持缩小函数返回类型的范围。由于
Demo
类型的解析取决于泛型类型参数
T
,因此与直接在返回类型注释中写入条件相同

如果我们重写
Demo
类型(仅用于演示目的),问题就会变得更清楚:

类型D={
正确:{
a:字符串
},
错误:{
b:字符串
}
}[`${T}`];
常量func=(参数:T):D=>{
如果(arg){
返回{a:“hello”};//类型{a:string;}不可分配给类型{a:string;}&{b:string;}”
}否则{
返回{b:world};//类型{b:string;}不可分配给类型{a:string;}&{b:string;}'
}
};
现在应该非常清楚的是,
D
在您为类型参数提供一个参数之前一直没有得到解决。这就是为什么
const out=func(true)已正确推断

我如何解决它

您几乎只限于使用类型断言,如
作为演示
,或者删除泛型类型参数并使用重载重写签名,如答案中所述

我怎样才能更好地理解这一点

看一看(另请参阅)。归结起来,TypeScript在使用条件类型时不支持缩小函数返回类型的范围。由于
Demo
类型的解析取决于泛型类型参数
T
,因此与直接在返回类型注释中写入条件相同

如果我们重写
Demo
类型(仅用于演示目的),问题就会变得更清楚:

类型D={
正确:{
a:字符串
},
错误:{
b:字符串
}
}[`${T}`];
常量func=(参数:T):D=>{
如果(arg){
返回{a:“hello”};//类型{a:string;}不可分配给类型{a:string;}&{b:string;}”
}否则{
返回{b:world};//类型{b:string;}不可分配给类型{a:string;}&{b:string;}'
}
};
现在应该非常清楚的是,
D
在您为类型参数提供一个参数之前一直没有得到解决。这就是为什么
const out=func(true)已正确推断

我如何解决它


您几乎只能使用类型断言,如
作为演示
,或者删除泛型类型参数并用重载重写签名,如回答中所述。

除了
之外,还有什么
扩展了真
?我认为没有,所以在这个特殊的例子中,我认为
func
需要泛型或重载,但不是两者都需要。重载为no
T
:当然,我只是没有从重载中删除泛型。除了
true
,还有什么
扩展了true
?我认为没有,所以在这个特殊的例子中,我认为
func
需要泛型或重载,但不是两者都需要。no
T
重载:当然,我只是没有从重载中删除泛型谢谢,我之所以选择这个作为答案,是因为这些讨论的链接实际上回答了我的问题,即为什么重载是解决这个问题的唯一方法,而不是条件返回类型。@aditya-NP,我记得在讨论之前,我花了很长时间问自己同样的问题。这是一个不幸的设计限制,从长远来看,它看起来会被重新考虑(毕竟,这里的推论确实有效)谢谢你,我之所以选择这个作为答案,是因为这些讨论的链接实际上回答了我的问题,即为什么超载是最重要的