对象可能是 TS 中的“空”或“未定义”错误

对象在 TS 中可能是 ‘null’ 或 ‘undefined’ 错误

Object is possibly ‘null’ or ‘undefined’ error in TS

当我们尝试访问可能具有 or 值的对象的属性时,会发生“对象可能为‘null’或‘undefined’”null错误undefined

要解决该错误,请在引用为空时使用可选链接进行短路,例如person?.address?.country.

对象可能为空或未定义

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

索引.ts
type Person = { address?: { // 👈️ may be null or undefined country?: string; city?: string; } | null; }; const person: Person = {}; // ⛔️ Error: Object is possibly 'null' or 'undefined'. console.log(person.address.country);

类型上的address属性Person标记为
可选
,也可以是
null.

这就是为什么我们无法安全地访问对象的countrycity属性的原因。

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

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; // 👇️ const result: string | undefined const result = person?.address?.city;

问号点 (?.) 语法在 TypeScript 中称为
可选链接null,类似于使用点表示法访问对象的嵌套属性,但如果引用为空(或
),它

不会导致错误
undefined,而是短路返回undefined.

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

另一种方法是使用简单的if语句作为
类型保护

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; // 👇️ checks for both null and undefined if (person.address != null) { console.log(person.address.country); console.log(person.address.city); }

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

一旦我们进入if块,TypeScript 就知道该属性是一个对象,而不是or addressnull undefined

请注意,我们使用了松散不等于 (!=),它同时检查null
undefined

松散比较涵盖了nulland undefined,因为在松散比较null中等于undefined

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

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

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = { address: { country: 'Austria', city: 'Linz', }, }; // 👇️ non-null assertion operator console.log(person.address!.city); // 👉️ "Austria" console.log(person.address!.country); // 👉️ "Linz"

感叹号是

TypeScript中的
非空断言运算符。

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

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

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

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

索引.ts
type Person = { address?: { country?: string; city?: string; streetNumber?: number; } | null; }; const person: Person = {}; if ( person?.address && typeof person.address.streetNumber === 'number' && person.address.streetNumber > 5 ) { console.log('success'); }

逻辑 AND (&&) 运算符确保该address属性不是nullor
undefined并且该streetNumber属性存在于对象上并且是 a
number在将它与 number 进行比较之前5

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

例如,这会失败:

索引.ts
type Person = { address?: { country?: string; city?: string; streetNumber?: number; } | null; }; const person: Person = {}; // ⛔️ cannot compare possibly undefined to number if (person?.address?.streetNumber > 5) { console.log('success'); }
结果的值可能为undefined,因为这是可选链接运算符 (?.) 短路时的返回值。

streetNumber属性的值可能为undefined,因此我们不能直接将其与 进行比较number

避免出现“Object is possibly nullor
undefined”错误的另一种常见方法是使用
逻辑 AND (&&)
运算符。

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; if (person.address && person.address.city) { // 👇️ const result: string const result = person.address.city; }
如果左边的值是假的(例如 ),逻辑与(&&)运算符将不会计算右边的值undefined

如果person.addressreturns undefined,那么person.address.city根本不会被评估,所以我们不会得到错误。

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

真值是所有非假值。

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

这就是 TypeScript 能够推断块中变量类型result原因
stringif

null在这种情况下,解决“Object is possibly or ”错误的更好方法undefined是使用
typeof
运算符。

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; if (person.address && typeof person.address.city === 'string') { // 👇️ const result: string const result = person.address.city; }

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

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

索引.ts
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = { address: { city: '' } }; if (person.address && person.address.city) { // 👉️ does NOT run console.log('⛔️ this does NOT run'); } else { // 👉️ else block runs console.log('✅ this runs'); }

else块在上面的示例中运行。

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

尽可能明确并使用typeof运算符总是更好,因为它可以帮助我们避免一些难以发现的错误。

结论

null当我们尝试访问可能是或的对象的属性时,会发生“对象可能为 null 或未定义”错误undefined要解决该错误,请使用可选的链接运算符或类型保护来确保在访问属性之前引用不是空的。