对象在 TS 中可能是 ‘null’ 或 ‘undefined’ 错误
Object is possibly ‘null’ or ‘undefined’ error in TS
当我们尝试访问可能具有 or 值的对象的属性时,会发生“对象可能为‘null’或‘undefined’”null
错误undefined
。
要解决该错误,请在引用为空时使用可选链接进行短路,例如person?.address?.country
.
下面是错误如何发生的示例。
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
.
这就是为什么我们无法安全地访问对象的country
或city
属性的原因。
为了解决这个问题,我们可以使用可选的链接 (?.) 运算符。
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; // 👇️ const result: string | undefined const result = person?.address?.city;
问号点 (?.) 语法在 TypeScript 中称为
可选链接null
,类似于使用点表示法访问对象的嵌套属性,但如果引用为空(或
),它
不会导致错误undefined
,而是短路返回undefined
.
另一种方法是使用简单的if
语句作为
类型保护。
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
属性是否不等于null
或undefined
。
if
块,TypeScript 就知道该属性是一个对象,而不是or 。 address
null
undefined
请注意,我们使用了松散不等于 (!=),它同时检查null
和
undefined
。
松散比较涵盖了null
and undefined
,因为在松散比较null
中等于undefined
。
console.log(null == undefined); // 👉️ true console.log(null === undefined); // 👉️ false
如果您确定该属性的值不能为null
or undefined
,则可以使用非空断言运算符。
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 这个值永远不会是null
or undefined
。
我们在address
属性之后立即使用它,所以我们告诉 TypeScript
person.address
永远不会有null
or的值undefined
。
如果您在if
语句中进行比较,请使用逻辑与 (&&) 运算符来确保属性的类型正确。
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
属性不是null
or
undefined
并且该streetNumber
属性存在于对象上并且是 a
number
在将它与 number 进行比较之前5
。
这是必需的,因为如果引用为空值(null
或undefined
),可选的链接运算符(?.)将返回undefined
并且 TypeScript 不允许我们undefined
与number
.
例如,这会失败:
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 null
or
undefined
”错误的另一种常见方法是使用
逻辑 AND (&&)
运算符。
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.address
returns undefined
,那么person.address.city
根本不会被评估,所以我们不会得到错误。
if
都必须为真才能使块运行。 if
真值是所有非假值。
JavaScript 中的假值是:null
, undefined
, false
, 0
, ""
(空字符串),NaN
(不是数字)。
这就是 TypeScript 能够推断块中变量类型的result
原因
。string
if
null
在这种情况下,解决“Object is possibly or ”错误的更好方法undefined
是使用
typeof
运算符。
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
更好。
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
。要解决该错误,请使用可选的链接运算符或类型保护来确保在访问属性之前引用不是空的。