Vue.js源码中`options?: ?Object`的双问号含义,为何TS中编写会报错?
核心前提
你在Vue2源码中看到的所有类型注解,不是TypeScript语法,是Flow的静态类型检查语法——这也是你在TS文件中编写oneVar:?string会直接触发报错的根本原因:Flow和TypeScript是两套独立的JS静态类型方案,语法规则并不通用。
两个问号的具体作用
结合源码里的写法,两个问号出现在不同位置时,对应完全不同的Flow语法规则:
- 冒号与类型之间的
?(对应代码里的before: ?Function、oneVar:?string写法)
这是Flow的可空(Maybe)类型标记,作用是约束当前属性的取值范围:- 该属性是所属类/对象上必须存在的,完全缺失该属性会触发类型检查报错(哪怕属性值是null,也必须把这个属性挂在实例上)
- 属性的合法取值只有三类:对应类型本身、
null、undefined - 其他任意类型(比如数字、布尔值、普通对象)都会被判定为不合法
比如oneVar:?string的实际含义是:这个属性必须存在,值可以是字符串、null、undefined三种,不能是其他类型。
- 属性/参数名与冒号之间的
?(对应代码里的isRenderWatcher?: boolean、options?: ?Object写法)
这是Flow的可选属性/可选参数标记,作用是标记当前的类属性/函数参数可以完全不存在,不会触发类型检查报错。
叠加写法的含义
源码中options?: ?Object是两种规则的叠加,对应的约束是:
- 调用Watcher构造函数时,可以完全不传
options这个参数(由参数名后面的?实现可选性) - 如果传入了
options参数,它的合法取值只有Object、null、undefined三类,不能是其他类型(由冒号后面的?实现可空性)
与TypeScript的语法差异
TypeScript中不存在“类型前加?标记可空”的规则:
- TS的可空类型需要通过联合类型实现,比如字符串可空要写为
string | null - TS的
?仅用于标记可选属性/参数,且位置固定在属性名/参数名和冒号之间 - 直接把Flow的
属性: ?类型写法搬到TS文件中,会被判定为语法错误。
内容的提问来源于stack exchange,提问作者PreciousnessX
相关产品推荐
相关产品推荐

