简体   繁体   English

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

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

This code fails to compile: 此代码无法编译:

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

because on the last 2 lines:因为在最后两行:

Property 'type' does not exist on type 'object'.(2339)类型“对象”上不存在属性“类型”。(2339)

...which I can understand by itself, but I do not understand why after "type" in node check, TS infers node to still be of type object instead of type { type: unknown; [key: string]: unknown } ...我自己可以理解,但我不明白为什么"type" in node之后,TS 推断node仍然是object类型而不是类型{ type: unknown; [key: string]: unknown } { type: unknown; [key: string]: unknown } , which would not trigger error . { type: unknown; [key: string]: unknown }不会触发 error

You should do this:你应该做这个:

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

Just need to check insonceof instead of typeof and use object["key"] method to access values instead of .key .只需要检查insonceof而不是typeof并使用object["key"]方法来访问值而不是.key Also, it's good practice to ensure that the item isn't an Array since instonceof [] === 'object' too此外,最好确保该项目不是数组,因为instonceof [] === 'object'

Unfortunately, the TypeScript built-in in operator type guard is not as powerful as you expect it to be.不幸的是,内置in操作员类型防护中的 TypeScript 并没有您期望的那么强大。

From a bare object , it will not infer that the tested property is available.从一个裸露的object ,它不会推断出测试的属性是可用的。 It can infer that it is indeed there, only if it is already potentially available , eg in one of a union-ed types.它可以推断它确实存在,只有当它已经潜在可用时,例如在联合类型之一中。 Ie the control flow will not make the tested property "appear", but only try to differentiate between union-ed types.即控制流不会使被测试的属性“出现”,而只会尝试区分联合类型。

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
}

Playground Link 游乐场链接


In your case, you could therefore specify a union for the node argument, with a possible type of eg { type: unknown } .因此,在您的情况下,您可以为node参数指定一个联合,可能的类型为{ type: unknown }

However, the unknown top type absorbs all other types in a union, so it would have to be replaced by everything else, eg using the special type {} to represent common types:然而, 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

Playground Link 游乐场链接

While the code is correct, TypeScript doesn't have the capability to infer { type: unknown } from "type" in node but this feature is currently in development虽然代码正确,但 TypeScript 无法从"type" in node推断{ type: unknown }但此功能目前正在开发中

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

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