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
            };
        }
    });