Typescript 在不知道函数的特定参数的情况下返回函数的泛型(泛型)
我被一个接受包含鉴别器的泛型的函数的类型定义所困扰 我需要的是确保一个函数总是返回Typescript 在不知道函数的特定参数的情况下返回函数的泛型(泛型),typescript,typescript-generics,Typescript,Typescript Generics,我被一个接受包含鉴别器的泛型的函数的类型定义所困扰 我需要的是确保一个函数总是返回MyType,而与泛型中类型的细节无关,但我希望这是“推断的”。例如,我不必编写返回的特定MyType,因为它将“合并”(甚至替换)返回值 例如,这里我接收到一个类型,它有3个相关类型,但只返回2个 接口MyType{ 标签:标签; 值:类型; } 类型SampleInputType=MyType | MyType | MyType; 常量sampleInputValue:SampleInputType={ 标签
MyType
,而与泛型中类型的细节无关,但我希望这是“推断的”。例如,我不必编写返回的特定MyType
,因为它将“合并”(甚至替换)返回值
例如,这里我接收到一个类型,它有3个相关类型,但只返回2个
接口MyType{
标签:标签;
值:类型;
}
类型SampleInputType=MyType | MyType | MyType;
常量sampleInputValue:SampleInputType={
标签:“一个数字”,
数值:10
};
//理想情况下,您希望接受任何MyType并返回任何MyType
//但不是我的类型
//只使用返回类型就可以了
常量myFunction=(输入)=>{
如果(input.tag==='a number'){
返回{
标签:“foo”,
值:true
};
}否则{
返回{
//我希望避免类型错误的示例,因为这会将返回值转换为任意值
tagx:'一个数字',//这应该是一个编译器错误
数值:10
}
}
};
//样本输出类型
类型SampleOutputType=MyType | MyType;
//仅myVal的可能性应仅为MyType和MyType
const myVal=myFunction(sampleInputValue);
如果(myVal.tag==='foo'){
常量b:boolean=myVal.value;//这是任意值:/
}
首先,如果鉴别器的值始终为a,则您可能应该将相应的参数设置为字符串
,以便编译器推断出这一点并捕获更多错误:
interface MyType<T extends string, V> {
tag: T;
value: V;
}
注意,输入类型是MyType
,我必须把它写出来。我想这没关系,正如你在问题中提到的;如果没有,我能想象的就是在这里给MyType
的泛型参数一些,这样你就可以把MyType
写成MyType
。不过,接下来:
嘿,你用tagx
得到了想要的错误。修复后,编译器会将myFunction()
视为以下类型:
const myFunction: (input: MyType<string, unknown>) =>
MyType<"foo", boolean> | MyType<"a number", number>
更新:如果希望“我希望函数返回一些
MyType
”的规范出现在函数级别而不是返回的值中,可以使用不同的帮助函数,如下所示:
const myType = <T extends string, U>(x: MyType<T, U>) => x;
const myTypeReturner = <I extends any[], M extends MyType<string, unknown>>(
x: (...args: I) => M) => x;
这也给了你一个错误。。。但不幸的是,这与你认为的“问题”相去甚远。编译器说“我不喜欢这个函数”,而不是“我不喜欢函数中的某一行”。所以这就是为什么我更喜欢上面概述的方法。但无论哪种方法都有效
谢谢你。我的问题不够具体,但我想在函数级别强制执行这一点,例如
constmyfunction:(something)=>OneOfMyType
或constmyfunction=():OneOfMyType..
。我想这还不可能吧?另一个问题是,类似的方法也适用于输入值,设置方式是使用MyType
makes,这样“tag”就不再是函数内部的“数字”|“foo”|“字符串”,而是“字符串”。对于输入,我不知道您如何期望编译器知道它,而不需要自己注释它。例如,您可以编写(输入:SampleInputType)=>…
,然后编译器将知道标记
是“一个数字”|“foo”|“一个字符串”
。我的意思是,这不是真的可以推断的,是吗?我当然不能通过查看函数实现来推断它。更新了答案,使其更接近“函数级别”。不,如果不指定泛型、任何类型的OneOf
、没有对或可能的直接支持,就无法对泛型类型进行注释。根据我的经验,Helper函数是最接近的。对于输入,我真的不知道如果不自己注释,编译器如何知道它。
对不起,你是对的。我已经有了这个类型,我只是想确定它的类型是MyType
,但这并不重要。
if (myVal.tag === 'foo') {
const b = myVal.value; // b is boolean
} else {
myVal.value.toFixed(2); // myVal.value is number
}
const myTypeReturner = <I extends any[], M extends MyType<string, unknown>>(
x: (...args: I) => M) => x;
const myFunction2 = myTypeReturner(
(input: MyType<string, unknown>) => { // error!
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type '{ tagx: string; value: number; tag?: undefined; }'
// is not assignable to type 'MyType<string, unknown>'
if (input.tag === 'a number') {
return {
tag: 'foo',
value: true
};
} else {
return {
tagx: 'a number',
value: 10
};
}
});