TypeScript 中的对象可能为“空”错误

TypeScript 中的 Object is possibly ‘null’ 错误

Object is possibly ‘null’ error in TypeScript

当我们尝试访问可能值为null. 要解决该错误,请使用可选的链接运算符在引用等于 时短路null,例如emp?.address?.country

对象可能为空

下面是错误如何发生的示例。

索引.ts
type Employee = { address: { country: string; city: string; } | null; // 👈️ could be null }; const emp: Employee = { address: null, }; // ⛔️ Error: Object is possibly 'null'.ts(2531) console.log(emp.address.country);

类型的address属性Employee可能是null,这会导致错误。

我们可以使用可选的链接 (?.) 运算符来解决这个问题。

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: null, }; // ✅ No errors console.log(emp?.address?.country); // 👈️ using optional chaining

问号点 (?.) 语法

在 TypeScript中称为
可选链接。

null这就像使用点符号来访问对象的嵌套属性,但如果引用为空(或),它不会导致错误undefined,而是短路返回undefined

这种方法通常用于从远程 API 获取数据或从文件中读取数据,其中某些属性可能没有值。

另一种方法是使用if充当
类型保护的简单语句。

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: null, }; // 👇️ check if not null or undefined if (emp.address != null) { console.log(emp.address.country); console.log(emp.address.city); }

我们使用if语句来检查emp.address属性是否不等于
nullundefined

一旦我们进入if块,TypeScript 就知道属性的类型 countrycity string

请注意,我们使用了松散不等于 (!=),它同时检查null
undefined您可以专门检查null严格不等于 (!==)。

松散比较涵盖两者nullundefined因为在松散比较null中等于undefined

索引.ts
console.log(null == undefined); // 👉️ true console.log(null === undefined); // 👉️ false

如果您确定该属性的值不能为 ,您也可以使用非空断言运算符null

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: { country: 'Germany', city: 'Hamburg', }, }; console.log(emp.address!.country); // 👉️ "Germany"

感叹号是

TypeScript中的
非空断言运算符。

它在不进行任何显式类型检查的情况下从类型中删除null和。undefined

当你使用这种方法时,你基本上告诉 TypeScript 这个值永远不会是nullor undefined

我们在address属性之后立即使用它,所以我们告诉 TypeScript
emp.address永远不会有nullor的值undefined

如果您在if语句中进行比较,请使用逻辑与 (&&) 运算符来确保属性的类型正确。

索引.ts
type Employee = { address: { country: string; city: string; num?: number; } | null; }; const emp: Employee = { address: null, }; if ( emp.address && typeof emp.address.num === 'number' && emp.address.num > 50 ) { console.log('success'); }

逻辑 AND (&&) 运算符在将它与数字进行比较之前确保该address属性不是null, 它num存在于address对象上并且是 a number50

这是必需的,因为如果引用为空(nullundefined),可选的链接运算符(?.)将返回undefined并且 TypeScript 不允许我们undefinednumber.

例如,这会失败:

索引.ts
type Employee = { address: { country: string; city: string; num?: number; } | null; }; const emp: Employee = { address: null, }; // ⛔️ could be undefined, so not allowed if (emp?.address?.num > 50) { console.log('success'); }

结果可能具有值,undefined因为这是可选链接 (?.) 运算符短路时的返回值。TypeScript 不允许我们将可能的undefined值与数字进行比较。

避免出现错误的另一种常见方法是

在访问属性时使用
逻辑与 (&&)运算符。

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: null, }; if (emp.address && emp.address.country) { // 👉️ emp.address.country is type string here console.log(emp.address.country.toUpperCase()); }
如果左边的值是假的(例如 ),逻辑与(&&)运算符将不会计算右边的值null

条件中的所有值if都必须为真才能使if块运行。

真值是所有非假值。

JavaScript 中的假值是:undefined, null, false, 0, ""
(空字符串),
NaN(不是数字)。

这就是 TypeScript 能够推断块中属性类型原因 emp.address.countrystring if

在这种情况下,解决“对象可能是”错误的更好方法null是使用
typeof
运算符。

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: null, }; if (emp.address && typeof emp.address.country === 'string') { // 👉️ emp.address.country is type string here console.log(emp.address.country.toUpperCase()); }

我们明确检查country属性的类型是否为字符串。这比检查该值是否是truthy因为空字符串在 JavaScript(和 TypeScript)中是虚假值要好。

这是一个示例,说明为什么使用typeof更好。

索引.ts
type Employee = { address: { country: string; city: string; } | null; }; const emp: Employee = { address: { country: '', city: '', }, }; if (emp.address && emp.address.country) { const result = emp.address.country; console.log(result); } else { // 👉️ else block runs console.log('✅ This block runs'); }

else块在示例中运行。

country属性指向一个空字符串(虚假值),因此在您的场景中仅检查该值是否为真可能还不够。

尽可能明确并使用typeof运算符总是更好。这有助于我们避免一些难以发现的错误。

结论

当我们尝试访问可能值为null. 要解决该错误,请使用可选的链接运算符或类型保护来确保
null在访问属性之前引用不存在。

发表评论