比如 type X = string | number ,如果定义函数返回类型是 X ,那么只要是 string 或 number 其中一个就可以。
如果想让函数两种类型都必须有返回(不同的分支返回不同的类型),是否有其他办法?
大致是这样的功能:
// 编译不通过
function a() : string && number {
return 123
}
// 编译不通过
function b() : string && number {
return 'hello'
}
// 编译通过
function c() : string && number {
if (...) {
return 123
}
return 'hello'
}
1
DOLLOR 2022-05-31 23:51:05 +08:00
没懂你想问什么,定义函数的时候返回值类型直接写“string | number”还不能达到你的需求么?
|
2
thinkershare 2022-05-31 23:55:56 +08:00
@DOLLOR 他想让编译器给他检查流程, 就是这个函数的返回必须必须即有 string 也有 number, 我目前是没想到有什么方法, 因为这个需求本质也是一种类型运算, 需要编译器检测函数返回类型, 然后组合. 但是目前 TS 似乎没有那个类型本身可用进行这种特殊的类型约束, 因为这个约束类型 never 这种, 需要超越类型本身的信息, 做分支流程检测.
|
3
jsq2627 2022-06-01 00:05:05 +08:00
function overloading https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads
|
4
ZE3kr 2022-06-01 00:07:46 +08:00
OP 想问的是如何保证这个函数有可能返回每一种类型
但问题是根据定义,只返回 string 或 number 中的一种,这个函数的返回值类型也属于 X 。不如约定一个自己的类型 Y ( Y 是一个 Function/Class ),这样只要返回的是 Y 你就知道一定是都有返回了。 Function/Method subtyping is always contravariant in its argument ProvideMore do(Take less); |
5
jsq2627 2022-06-01 00:21:08 +08:00
https://www.typescriptlang.org/docs/handbook/2/conditional-types.html 这篇文档似乎是近期更新的,专门讲解 conditional type
|
6
learningman 2022-06-01 00:48:00 +08:00 via Android
你想要的是 overload
|
7
Rocketer 2022-06-01 00:55:40 +08:00 via iPhone
我还是看不懂需求,一个输入返回一个值,这个返回值不可能既是数字又是字符串。
如果输入不同返回不同,那不是单元测试要做的事吗? |
8
Opportunity 2022-06-01 01:01:34 +08:00 1
|
9
liuzhaowei55 2022-06-01 01:01:58 +08:00 via iPhone
题主可以自己拆解这个函数为两个子函数分别处理两个分支,然后在外部包装一层,判断入参应该走哪个分支,即拆分了逻辑又对响应数据类型做了保证。
|
10
iosyyy 2022-06-01 01:17:05 +08:00
楼主的意思是强制要求返回 number+string 吧上面感觉有点跑题
我个人觉得还是分成两个函数解决好点 你可以做一个 map 映射一下然后分别调用 |
11
vision1900 2022-06-01 01:30:29 +08:00
函数本身只是个过程,它在执行前不知道究竟哪些分支会被执行。如果一个函数即可能返回 string 也可能返回 number ,而且具体返回 string 还是 number 的判断是在函数内,那么他就只能返回 string | number.
这个问题本身无解。 假设原来的 function 是这样: ```typescript // 获取日本人的出生年(尽可能用国号纪年) function getBirthYear(age: number) { const year = (new Date()).getFullYear() - age if (year > 2019) { return `令和${year - 2019}年` } else if (year > 1989) { return `平成${year - 1989}年` } else if (year > 1926) { return `昭和${year - 1926}年` } else { return year } } console.log(getBirthYear(100)) // 1922 console.log(getBirthYear(24)) // "平成 9 年" ``` |
12
muzuiget 2022-06-01 01:33:03 +08:00
估计要的是泛型,也就是尖括号用法
getStringOrNumber<string>('aString'); getStringOrNumber<number>(1); |
13
shakukansp 2022-06-01 01:40:35 +08:00
overload
|
14
renhou 2022-06-01 07:50:05 +08:00
可以的,函数的重载
|
15
lneoi 2022-06-01 09:15:10 +08:00
听着像是重载,一种输入对应一种返回类型
|
16
raykle 2022-06-01 09:48:54 +08:00
|
17
zingwu 2022-06-01 10:08:25 +08:00
重载吧
|
18
zhuweiyou 2022-06-01 12:04:34 +08:00
泛型
|
19
jeffhong 2022-06-01 16:06:35 +08:00 via iPhone
你需要 sum type ,大多数编程语言不支持。不过你可以用 product type 来模拟下。
|
20
qbqbqbqb 2022-06-02 11:35:41 +08:00
@raykle OP 需求应该是想对 union type 返回值做反向的 exhaustiveness check.
正向的 exhaustiveness check 主要是针对这种值的读取的,比如说有些语言的 switch-case 或模式匹配如果缺了几个 case 又没有显式写 default case 的话编译器就会产生 warning 甚至 error 这样。一般不针对赋值、返回值等写入操作。 而 OP 希望对函数返回值的写入也可以进行这种 check 。就比如说你有一个类型 type X = string | number 然后定义一个函数 getStringOrNumber(): X 这时如果函数体内只有 return string 的语句而没有 return number 的语句, [也就是说这个 X 类型里有几种情况没有用到,可以改成 getStringOrNumber(): string 也不出错] ,OP 希望遇到这种情况编译器可以提供 warning 或者 error 。 |
21
qbqbqbqb 2022-06-02 11:58:16 +08:00
这个需求在 TypeScript 里其实不好做。因为 ts 里有一种 literal type 的东西。比如你的例子里的 c 函数,如果不手动指定返回类型的话,你以为编译器推断出的类型是 string|number ,结果其实是"hello"|123 ,也是一种比 string|number 更窄的类型,那它该不该报错呢? 按照你的需求应该是不报错,但是按照 ts 的类型系统"hello"|123 和 number 都是 extends string|number ,并不好区分。
|