ts 函数重载的问题
下面的3个函数的重载。
test写法的重载会报错。
test1和test2就是正常的,这是为什么?
function test (): void;
function test(name: string): string;
function test(name: number): number;
function test (name?: string | number,) {
if(typeof name === 'string') {
return '1';
} else if(typeof name === 'number') {
return 1;
}
return;
}
function test2 (): void;
function test2(name: string): string;
function test2(name: number): number;
function test2 (name?: string | number,) {
if(typeof name === 'string') {
return name;
} else if(typeof name === 'number') {
return name;
}
return;
}
function test3 (): void;
function test3(name: string): string;
function test3(name: number): number;
function test3 (name?: string | number,): string | number | void {
if(typeof name === 'string') {
return '1';
} else if(typeof name === 'number') {
return 1;
}
return;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
多少天了,我感觉还没几个赞就离谱,采纳回答 @zangeci 四个赞更离谱,@陈安柱 一个不明所以的都拿了两赞,气炸了气炸了。为什么 这串 TS 代码 没有报错呢?你们的回答能解释这个问题吗?
提问者 @yepnope 私信起来也是不知所云,“没看到我的答案”?如果你说的是采纳前没看到,现在也可以改呀,设个不太全面的第一不是误人子弟?
抱怨结束,原答案在下面。
函数重载返回值必须是函数实现的子集,或者超集。
TS 在检查一个函数重载的返回值与其实现的返回值是否兼容时,是直接看整体的。
对于
test
,我只以第二个函数重载为例,该重载返回值是string
,其函数实现返回值是"1" | 1 | undefined
,string
是"1" | 1 | undefined
的子集吗?不是。是超集吗?不是。所以报错。对于
test2
,函数实现返回值是string | number | undefined
,也只以第二个函数重载为例,string
是string | number | undefined
的子集吗?是,所以不报错。对于
test3
,在函数实现上标记了返回值,TS 的检查分为两部分,一部分是实现内的返回是否符合标记的返回,另一部分和上述一样,不过以其标记值作为该函数实现的返回值。“子集或超集” 这句,文档里有写吗?没写。但源码里有写。TS 的源码毫不吝啬变量名长度,是很好看的。在 src/compiler/checker.ts 的 17253-17268 行,因为文件太大 GitHub 看不了,我就复制过来:
除了源码里有写,还有一堆相关 issue(这不一定算个好事因为 Duplicate 链真的好长)。近期的 #44661 值得注意,TS 成员再次提到了这个子集或超集的判断方式,也开始考虑是否纳入交集判断。
因为类型不兼容,你可能觉得返回字符1和数字1是符合
string
和number
的,但需要注意的是函数重载列表必须是函数实现的子集也就是前三个的类型是第四个函数实现的类型子集。而实现里返回值是
‘1’|1|undefined
;反过来了,这个需要注意理解,所以下面这种是成立的没有一个类型是匹配的
常量
"1"
和1
会被推断为字面量类型。对于
test
,推断返回类型会是"1" | 1 | undefined
,不包含重载声明中的string
和number
。解决办法:
as
扩大"1"
和1
的类型,比如return "1" as string;
string | number | undefined
来学习我的课程:TypeScript从入门到实践 【2021 版】 - 思否编程