Typescript 函数类型的判别并集?

Typescript 函数类型的判别并集?,typescript,Typescript,我似乎不知道如何区分函数类型的有区别的联合体的成员。请参见以下示例: type\u NumFunc=(n:number)=>string; 类型_StrFunc=(s:string)=>string; 接口NumFunc扩展了NumFunc{uu类型:'NumFunc';} 接口StrFunc扩展了_StrFunc{u类型:'StrFunc';} Func类型=NumFunc | StrFunc; 让myNumFunc=((n:number)=>`Hello x${n}!`)作为NumFunc;

我似乎不知道如何区分函数类型的有区别的联合体的成员。请参见以下示例:

type\u NumFunc=(n:number)=>string;
类型_StrFunc=(s:string)=>string;
接口NumFunc扩展了NumFunc{uu类型:'NumFunc';}
接口StrFunc扩展了_StrFunc{u类型:'StrFunc';}
Func类型=NumFunc | StrFunc;
让myNumFunc=((n:number)=>`Hello x${n}!`)作为NumFunc;
让myStrFunc=((s:string)=>`Hello,${s}!`)作为StrFunc;
让funcGen=(n:number):Func=>n%2==0?myNumFunc:myStrFunc;
for(设i=0;i<2;i++)
{
设func=funcGen(i);
开关(功能型)
{
案例“NumFunc”:
控制台日志(func(3));
打破
案例“StrFunc”:
console.log(func('World!'));
打破
违约:
控制台错误(func);
console.error('这是怎么发生的?');
打破
}
}
我预计该计划的输出应为:

你好,x3

你好,世界


但是如果您这样做,您将看到每个迭代都会调用默认情况。只需记录
func
即可显示函数对象,但尝试访问对象上的
\uu type
会抛出一个错误,指出
func
的类型为
从不
。为什么这种方法不起作用,有没有允许使用函数类型的有区别的并集的方法?

好问题。我们需要理解TypeScript没有运行时。它的意思是,运行时中没有类型的表示。类型只是JS本身中存在的真实结构上的别名。换句话说,定义TS类型时,需要告诉编译器该类型在运行时表示的确切结构

这意味着,如果我说某个类型
A
表示为
{x:string}
,那么当我创建一个类型
A
的值时,我需要将某个对象放在那里,并将x属性作为string。TypeScript永远不会自己创建这样的结构。它需要通过服务器响应来创建或提供。因此,这是运行时的责任

回到您的问题-问题是您正在定义您的函数具有
\uuu type
属性形式的鉴别器,但您从未在其中任何一个中真正设置此属性。因此,您是在愚弄类型系统,说f是NumFunc,g是StrFunc,但这在运行时中没有真正的表示。开关在运行时工作,并且没有您使用的
\u type
属性

要解决此问题,您需要手动将此属性附加到函数。例如:

let myStrFunc = ((s: string) => `Hello, ${s}!`) as StrFunc;
myStrFunc.__type = 'StrFunc'


let myNumFunc = ((n: number) => `Hello x${n}!`) as NumFunc;
myNumFunc .__type = 'NumFunc'

现在,这两个功能都需要区分,应该可以工作了。希望有帮助。

问得好。我们需要理解TypeScript没有运行时。它的意思是,运行时中没有类型的表示。类型只是JS本身中存在的真实结构上的别名。换句话说,定义TS类型时,需要告诉编译器该类型在运行时表示的确切结构

这意味着,如果我说某个类型
A
表示为
{x:string}
,那么当我创建一个类型
A
的值时,我需要将某个对象放在那里,并将x属性作为string。TypeScript永远不会自己创建这样的结构。它需要通过服务器响应来创建或提供。因此,这是运行时的责任

回到您的问题-问题是您正在定义您的函数具有
\uuu type
属性形式的鉴别器,但您从未在其中任何一个中真正设置此属性。因此,您是在愚弄类型系统,说f是NumFunc,g是StrFunc,但这在运行时中没有真正的表示。开关在运行时工作,并且没有您使用的
\u type
属性

要解决此问题,您需要手动将此属性附加到函数。例如:

let myStrFunc = ((s: string) => `Hello, ${s}!`) as StrFunc;
myStrFunc.__type = 'StrFunc'


let myNumFunc = ((n: number) => `Hello x${n}!`) as NumFunc;
myNumFunc .__type = 'NumFunc'

现在,这两个功能都需要区分,应该可以工作了。希望有帮助。

让myNumFunc=Object.assign((n:number)=>`Hello x${n}!`,{uu键入:'NumFunc'}作为常量);让myStrFunc=Object.assign((s:string)=>`Hello,${s}!`,{uu类型:'StrFunc'}作为常量)
.Or
让myNumFunc=Object.assign((n:number)=>`Hello x${n}!`,{uu type:'NumFunc'}作为常量);让myStrFunc=Object.assign((s:string)=>`Hello,${s}!`,{uu类型:'StrFunc'}作为常量)