当前位置: 首页 > Web前端 > HTML

在TypeScript中使用条件类型实现函数重载

时间:2023-03-29 12:48:36 HTML

假设有这样一个函数,你会如何声明它的类型?functionadd(a,b){returna+b;}add函数可能有两种情况:参数a和b是number类型,返回值是number类型参数a和b是string类型,和返回值是字符串类型使用函数重载可以解决吗?首先,您可以通过声明多个函数类型来实现add函数的重载声明。函数添加(a:字符串,b:字符串):字符串;函数添加(a:数字,b:数字):数字;函数添加(a:任何,b:任何){返回a+b;}添加(1,2);//函数添加(a:数字,b:数字):numberadd('x','y');//functionadd(a:string,b:string):string这个方法显然不错,但是有一个小问题:当传入的参数类型为number|string时,会出现意外的类型错误。leta:string|number;add(a,a);/*第一个重载(共2个),“(a:string,b:string):string”,出现以下错误。'string|类型的参数number'不可分配给'string'类型的参数。类型“数字”不可分配给类型“字符串”。第二个重载(2个),'(a:number,b:number):number',给出以下错误。'string|类型的参数number'不可分配给类型为'number'的参数。类型“字符串”不可分配给类型“数字”。*/这是因为当我们使用函数重载时,TypeScript会使用这些重载来一个一个地比较,直到匹配到一个合适的类型重载。但是很明显,我们声明的两个重载中的变量类型,number和string,都不匹配number|string,所以会出现类型错误。使用泛型怎么样?然后,您可能还会考虑使用泛型来声明类型以构建通用模式。函数添加(a:T,b:T):T;函数添加(a:任何,b:任何){返回a+b;}consta:数字=0;constb:string='str';add(a,a);//functionadd(a:number,b:number):numberadd(b,b);//functionadd(a:string,b:string):string方法看起来也不错,但是也有一个小问题:当传入一个字面量类型的参数时,会认为参数的类型和参数的值是同一类型范围。例如:add(1,2);//函数add<1|2>(a:1|2,b:1|2):1|2参数1的类型是1,不是number,就像我们声明typeT=1|2一样;同理,函数类型声明中的泛型T必须同时满足第一个参数1和第二个参数2,所以T的类型变为1|2;同样,如果传入的变量a和b没有显式声明number和string时也会出现这个问题。条件类型可能更好事实上,当需要重载此类函数时使用条件类型可能会有更好的结果。函数添加(a:T,b:T):Textendsnumber?数字:字符串;functionadd(a:any,b:any){returna+b;}add(1,2);//函数add<1|2>(a:1|2,b:1|2):numberleta:number|string;add(a,a);//函数add(a:字符串|数字,b:字符串|数字):字符串|number该方法首先通过泛型方法获取参数的类型,然后使用条件类型进行判断,从而获取正确的类型。这种方法比前两种方法写起来更复杂,但是类型会更准确。当一个函数需要类型重载时,考虑使用条件类型来实现它。