繁体   English   中英

类型“对象”上不存在属性“类型”,即使在“类型”检查之后

[英]Property 'type' does not exist on type 'object', even after `"type" in` check

此代码无法编译:

const nodeIsUseless = (node: unknown) =>
  node !== null &&
  typeof node === "object" &&
  "type" in node &&
  typeof node.type === "string" &&
  node.type === "JSXText";

因为在最后两行:

类型“对象”上不存在属性“类型”。(2339)

...我自己可以理解,但我不明白为什么"type" in node之后,TS 推断node仍然是object类型而不是类型{ type: unknown; [key: string]: unknown } { type: unknown; [key: string]: unknown }不会触发 error

你应该做这个:

const nodeIsUseless = (node: unknown) =>
  node !== null &&
  node !== undefined &&
  node instanceof Object &&
  !Array.isArray(node) &&
  "type" in node &&
  typeof node["type"] === "string" &&
  node["type"] === "JSXText";

只需要检查insonceof而不是typeof并使用object["key"]方法来访问值而不是.key 此外,最好确保该项目不是数组,因为instonceof [] === 'object'

不幸的是,内置in操作员类型防护中的 TypeScript 并没有您期望的那么强大。

从一个裸露的object ,它不会推断出测试的属性是可用的。 它可以推断它确实存在,只有当它已经潜在可用时,例如在联合类型之一中。 即控制流不会使被测试的属性“出现”,而只会尝试区分联合类型。

declare const o: object;
if ("type" in o) {
  o.type // Error: Property 'type' does not exist on type 'object'.
//^? object
}

declare const u: Number | String; // Note: using class only for the sake of the demo
if ("toFixed" in u) {
  u.toFixed(); // Okay
//^? Number
}

游乐场链接


因此,在您的情况下,您可以为node参数指定一个联合,可能的类型为{ type: unknown }

然而, unknown的顶级类型吸收了联合中的所有其他类型,因此必须将其替换为其他所有类型,例如使用特殊类型{}来表示常见类型:

const nodeIsUseless = (node: undefined | null | {} | { type: unknown }) =>
  node !== null &&
  typeof node === "object" &&
  //     ^? {} | { type: unknown } | undefined
  "type" in node &&
  //        ^? {} | { type: unknown }
  typeof node.type === "string" && // Okay
  //     ^? { type: unknown }
  node.type === "JSXText"; // Okay

游乐场链接

虽然代码正确,但 TypeScript 无法从"type" in node推断{ type: unknown }但此功能目前正在开发中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM