[英]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
}
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
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.