这算不算是静态类型系统的缺憾

2022-06-30 11:11:01 +08:00
 fpure

以这段 typescript 代码为例,f 期待一个类型为 10 的参数,x 等于 10 ,但是因为 x 的类型为 number ,所以不匹配

9109 次点击
所在节点    程序员
106 条回复
yazinnnn
2022-06-30 12:37:46 +08:00
能编译通过才是类型系统的悲哀
imKiva
2022-06-30 12:40:27 +08:00
imKiva
2022-06-30 12:41:51 +08:00
@imKiva #42 补充一下:“但是在 ts 里不行” 除非 as const
uni
2022-06-30 12:42:54 +08:00
目前为止人类的的程序静态分析的技术还没到这个水平吧,那只能期待未来的科研成果了
baobao1270
2022-06-30 12:55:19 +08:00
1. Python 不是静态类型,但是又 type hint ,在 Python 里是可以指定 literal value 的,比如类型为 str 且仅取值 "month" 和 "day"。支持泛型的语言,也大多支持泛型查询( where T : SomeClass )。
2. 如果要对函数输入的数据进行验证(比如“只能输入全体偶数”),正确的做法是在函数内验证,如果不通过就抛 Exception 。
3. 如果参数值的集合是有限可数的,比如 ACTIVE = 0, HIDDEN = 1, DELETED = 2, 那么应该使用 enum 而不是 int 。
abcbuzhiming
2022-06-30 12:57:42 +08:00
类型系统不就是为了限制有些人啥也不管的往函数里任意传参的吗?改动楼主说的,那不又变成想传啥就传啥了?
zhuweiyou
2022-06-30 13:00:51 +08:00
什么场景会这么写
ifdef
2022-06-30 13:05:30 +08:00
建议多读读 typescript 的文档,虚心一点,反复读几遍 union type 和 type narrowing 的相关内容。
fpure
2022-06-30 13:30:14 +08:00
@aguesuka 我了解了一下 Refinement type ,有点意思,学到了👍
Mexion
2022-06-30 13:32:44 +08:00
这根本不是什么问题,参数类型为 10 ,那就一定得传 10 ,number 类型可以是任何数,凭什么让你传
haolongsun
2022-06-30 13:37:10 +08:00
。。能问出这个问题也是极品,你都定义类型只能是 10 ,你还要传进去 Number ,Number 可是 any ,定义域范围都不一样。
Kawa
2022-06-30 13:45:08 +08:00
这算什么缺憾…
没有 runtime type check 才是 typescript 最大的缺憾, 作为一个所谓的强类型语言结果在运行时类型全给抹除掉, 然后该报错还得报错.
typescript 在编译期为了保证所谓的静态类型, 程序员不得不为了过编而编写更多的屎代码, 比如 document.append 完一个元素再 query 他需要判空, 不然不给过编.

这还不算, 这个例子比较极端.
你用 ts, 但是你用的模块是纯 js, 或者模块的 ts 类型写得跟屎一样, 那你这个模块就会用得特别痛苦, 如果处理不好, 这份痛苦就会在整个代码仓库里蔓延.

写了这么久 ts, 我还是觉得 ts 只配当一个文档工具, 在类型检查上 ts 只会让程序员浪费更多的时间跟 ts 编译器打架.
cenbiq
2022-06-30 13:50:18 +08:00
编译器没错,这是因为你的 let x 的声明类型是 number ,虽然你后期赋值为 10 ,但它的类型不是 10 而是 number 。
cenbiq
2022-06-30 13:53:01 +08:00
@cenbiq 噢看错了你的问题
nothingistrue
2022-06-30 13:58:28 +08:00
给换一个简单的强类型语言来描述:

// 类型关系:Child extend Base

// 定义
void oneMethod(Child x){}

// 使用
Base y = new Child();
oneMethod(y); // 出现编译错误

然后你就会发现问题在哪里了,你给 y 定义了类型是 Base ,但用得时候却期望它是根据运行时推测出来的 Child 。

这怎么会是静态类型系统的缺憾,这正是强类型语言的基本特性。研究一个东西的特性是不是它的缺憾,这形同与研究人吃饭是不是有缺憾。楼主应该先学习一下强类型语言是什么。
fpure
2022-06-30 14:13:54 +08:00
@nothingistrue 你没理解我的问题,我当然知道什么是静态类型,这里 typescript 需要做类型断言,放到 Java 里面就是强制类型转换,我的问题是有没有可能制造一种类型系统在实际类型匹配的情况下自动地做这个类型断言、类型转换
Leviathann
2022-06-30 14:14:44 +08:00
这里的原因难道不是用户的手动标注优先级高于 tsc 的自动推断吗?而且 let 天然就是倾向宽松的推断
const a = 10
f(a)
就没问题

就算这么写
后面加一个
if ( x === 10 ) {
f(x)
}
也行,利用 tsc 的控制流分析
zsxeee
2022-06-30 14:18:38 +08:00
我猜你想要检查器在每次赋值的时候自动 smart cast 收缩类型。比如赋值为 10 相当于直接后面直接有了 (x === 10) 为 true 。可以理解但是是不可行的,这是让检查器猜测人的意图。

譬如 y 变量显式生命为 number ,赋值为 10 。但我逻辑上不允许将其传入 f() 中,这不是又回到人自己判断类型了吗?

正确的做法是:
1. 使用 const 且不显式声明类型
https://imgur.com/fud80Cr

2. 手动检查类型,让检查器自动 cast 类型
https://imgur.com/j0YS8FN
nothingistrue
2022-06-30 14:18:38 +08:00
@fpure #56
先回答你这个 “我的问题是有没有可能制造一种类型系统在实际类型匹配的情况下自动地做这个类型断言、类型转换”:
有,就是动态类型语言或者弱类型语言,原生 JavaScript 就是典型。

然后你再回头看看你到底知不知道什么是静态类型。
otakustay
2022-06-30 14:21:04 +08:00
这是控制流分析的问题了,其实是能够分析出来“调用 f 的时候 x 只有可能为 10”并过去的,但这个太损性能了,你不会想要的

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

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

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

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

© 2021 V2EX