TypeScript 能强制函数必须返回两种类型吗?

2022-05-31 23:32:39 +08:00
 iqoo

比如 type X = string | number ,如果定义函数返回类型是 X ,那么只要是 string 或 number 其中一个就可以。

如果想让函数两种类型都必须有返回(不同的分支返回不同的类型),是否有其他办法?

2627 次点击
所在节点    程序员
21 条回复
DOLLOR
2022-05-31 23:51:05 +08:00
没懂你想问什么,定义函数的时候返回值类型直接写“string | number”还不能达到你的需求么?
thinkershare
2022-05-31 23:55:56 +08:00
@DOLLOR 他想让编译器给他检查流程, 就是这个函数的返回必须必须即有 string 也有 number, 我目前是没想到有什么方法, 因为这个需求本质也是一种类型运算, 需要编译器检测函数返回类型, 然后组合. 但是目前 TS 似乎没有那个类型本身可用进行这种特殊的类型约束, 因为这个约束类型 never 这种, 需要超越类型本身的信息, 做分支流程检测.
jsq2627
2022-06-01 00:05:05 +08:00
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);
jsq2627
2022-06-01 00:21:08 +08:00
https://www.typescriptlang.org/docs/handbook/2/conditional-types.html 这篇文档似乎是近期更新的,专门讲解 conditional type
learningman
2022-06-01 00:48:00 +08:00
你想要的是 overload
Rocketer
2022-06-01 00:55:40 +08:00
我还是看不懂需求,一个输入返回一个值,这个返回值不可能既是数字又是字符串。

如果输入不同返回不同,那不是单元测试要做的事吗?
Opportunity
2022-06-01 01:01:34 +08:00
你需要 tsd ,实例里就有你说的内容

https://github.com/SamVerschueren/tsd#strict-type-assertions
liuzhaowei55
2022-06-01 01:01:58 +08:00
题主可以自己拆解这个函数为两个子函数分别处理两个分支,然后在外部包装一层,判断入参应该走哪个分支,即拆分了逻辑又对响应数据类型做了保证。
iosyyy
2022-06-01 01:17:05 +08:00
楼主的意思是强制要求返回 number+string 吧上面感觉有点跑题
我个人觉得还是分成两个函数解决好点 你可以做一个 map 映射一下然后分别调用
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 年"
```
muzuiget
2022-06-01 01:33:03 +08:00
估计要的是泛型,也就是尖括号用法

getStringOrNumber<string>('aString');
getStringOrNumber<number>(1);
shakukansp
2022-06-01 01:40:35 +08:00
overload
renhou
2022-06-01 07:50:05 +08:00
可以的,函数的重载
lneoi
2022-06-01 09:15:10 +08:00
听着像是重载,一种输入对应一种返回类型
raykle
2022-06-01 09:48:54 +08:00
OP 需求没描述清楚。

@muzuiget 乍一看我也觉得是泛型

type X = string | number
getStringOrNumber<X>(params: X): X
zingwu
2022-06-01 10:08:25 +08:00
重载吧
zhuweiyou
2022-06-01 12:04:34 +08:00
泛型
jeffhong
2022-06-01 16:06:35 +08:00
你需要 sum type ,大多数编程语言不支持。不过你可以用 product type 来模拟下。
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 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/856580

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX