关于经常询问的 TypeScript 字段类型 null 报错问题

经常有用户反馈,他们如下的代码会在 IDE 中报错:

property(Material)
public material: Material = null;

出错原因

material: Materialmaterial 字段声明为 Material 类型,这个意思就是 在任何时候 拿到 material 他都是一个 Material

= null,告诉它将 material 初始化为 空值 null。那么与上条说法违背。

这便是,TypeScript 的 严格类型检查。它要求你将类型对上号。TypeScript 编辑器是默认开启该选项的,Creator 也不例外。

解决办法

匹配它们的类型

既然 material 初始化为 空值 null,那么它的确可能是空值,那么可以这样声明:

public material: Material | null = null;

material: Material | nullmaterial 声明为 “既可能是 Material,也可能是 null”。

这样的缺点是:

  1. 后续使用 material 的时候需要判定它是否是空值,否则 TypeScript 会报告给你:它可能是空值,你需要处理是空值的情况。

  2. 写法真长。

断言

为什么 material 可能是空值?因为它确实一开始是空值,然后在 Cocos Creator 中我们通过拖拖拉拉之后,Creator 帮我们赋值进去。

那我们就想办法告诉 TypeScript,它就是 Material,虽然它一开始是空值,但你别管,我后续任何时候访问它,它都是 Material

有以下几种写法来做这件事:

material: Material = null!;

感叹号 ! 告诉 TypeScript 强制null 转换为 Material 类型。

同样地,初始化为 undefined 也没问题:

material: Material = undefined!;

感叹号 ! 告诉 TypeScript 强制undefined 转换为 Material 类型。

其实,在标准的 JavaScript 语法里,是可以不给初始化式的,这样的字段将被初始化为 undefined

class C {
  @property(Material)
  material; // undefined
}

在 TypeScript 里也允许这么做,不过你得提示一下 TypeScript,以上它跳过这里的类型检查:

material!: Material;

OK,这里你将得到一个虽然声明为 Material,但是初始化为 undefined 的字段。

和 TypeScript 严格空值检查说拜拜

当然了,如果你是非常不喜欢 TypeScript 的类型系统,你更喜欢所有事 靠自己确保,那么你可以关闭严格类型检测。在 <项目目录>/tsconfig 里,加上选项:

"extends": "./temp/tsconfig.cocos.json",
"compilerOptions": {
  "strictNullChecks": false // 关闭它
}

即使不是必须,我们仍然建议您保留这个选项,因为它可能帮你检测到非常多潜在的 Could not read "xx" property of null or undefined 错误。

13赞

= null还可能出现构建的时候初始化值了,但是使用的时候发现又被赋值为空了。

这种情况一版就是在编辑器中没给这个字段拖值。还有一种很少见的情况是组件的 destroy() 已经调用了还在访问。

.还是默认别开严格吧. 要是场景真的忘记放入组件挂件. 查个认为操作失误要找半年.除非所有开发者都不用挂件了!

其次严格模式 就这都爆红, image

其次移除了好多的2.x接口 但是那个3.0手册超链接目前全部还是失效的

这里爆红的原因是 UIOpacity 组件有可能不存在,确实建议做一下容错处理,或者用 !

哪个手册?

手册能打开了,昨天第一时间试了下没打开

提示错误的小问题还挺多的.

感谢反馈!

material: Material = <any>null; 要不你有个函数func(mat: Material)想传入material的时候就又红了, 修改类型这玩意是传染的。

默认还是关闭严格模式吧,第一次用血压拉满