打字稿中 obj.prop 和 obj['prop'] 的区别?

Posted

技术标签:

【中文标题】打字稿中 obj.prop 和 obj[\'prop\'] 的区别?【英文标题】:Difference between obj.prop and obj['prop'] in typescript?打字稿中 obj.prop 和 obj['prop'] 的区别? 【发布时间】:2022-01-21 20:11:27 【问题描述】:

在使用@babel/parser解析一些字符串并得到一个ast后,我在按obj.prop类型记录ast时遇到错误,但在使用obj['prop']类型时它可以工作

import  parse  from "@babel/parser";
import traverse from "@babel/traverse";

const ast = parse('key: "something"', 
    sourceType: "module",
    plugins: ["typescript"],
);

// Property 'declaration' does not exist on type 'Statement'.  Property 'declaration' does not exist on type 'BlockStatement'.ts(2339)
console.log(ast.program.body[0].declaration.properties);
// it's good
console.log(ast.program.body[0]["declaration"].properties);

我对这两种写法的区别感到困惑?

感谢回答

【问题讨论】:

【参考方案1】:

您可以在 javascript/typescript 中访问对象的属性:

    点属性访问器:object.property 方括号属性访问:object['property']

何时使用:

如果提前知道属性名称,请选择 dot 属性访问器。

例如。

const hero = 
  name: 'XYZ'
;

这里的属性是提前知道的,所以我们可以使用 hero.name

当属性名称是动态的(即在运行时确定)时,选择 括号属性访问器。

例如:

const property = 'name';
const hero = 
  name: 'XYZ'
;

// Square brackets property accessor:
hero['name'];   //output => 'XYZ'
hero[property]; //output => 'XYZ'

这里的属性是在运行时确定的,所以我们使用方括号。

所以如果你在运行时确定的属性上使用属性点访问器,打字稿会给你错误

类型 hero 上不存在属性“名称”。

访问属性没有好坏之分。根据您的具体情况选择。

希望这个明确的对象属性访问器。

【讨论】:

谢谢你的回答,能不能简单理解一下方括号属性访问的使用范围更广? @happyHacking 正如我在答案中提到的,当转译器事先不知道对象属性时,使用方括号。在您的示例中,数据可能来自 API,因此您可以使用方括号。如果你想使用点访问器,那么你必须映射响应创建模型类。【参考方案2】:

您可以使用点表示法或方括号表示法访问打字稿中的属性。不过,两者在错误方面存在差异,具体取决于编译器选项。

如果您将noImplictAny 设置为false(这是默认设置),即使无法在编译时检查属性是否有效,您也不会收到括号表示法错误,您只会得到一个隐式@ 987654328@。所以ast.program.body[0]["declaration"] 将是any,并且打字稿不会检查后面的.properties。 Playground Link

如果您将noImplictAny 设置为true,typescript 将抱怨无法检查declaration 确实是ast.program.body[0] 的属性,并且您将得到两者的错误(诚然,错误略有不同)Playground Link

在访问它的成员之前,您可能希望缩小ast.program.body[0] 的类型。这是一种将ast.program.body[0] 缩小为表达式语句,然后缩小为具有properties 成员的对象表达式的方法:

import  parse  from "@babel/parser";
import  isExpressionStatement, isObjectExpression  from "@babel/types";

const ast = parse('(key: "something")', 
    sourceType: "module",
    plugins: ["typescript"],
);

let firstStatement = ast.program.body[0];
if (!isExpressionStatement(firstStatement) || !isObjectExpression(firstStatement.expression)) 
    throw Error("Expected statement not found");


console.log(firstStatement.expression.properties);

Playground Link

注意:我将 key: "something" 更改为 (key: "something")。我假设您正在尝试解析对象文字。你的版本实际上是一个块语句,里面有一个带标签的语句。 Block statement 与 Object literal

【讨论】:

以上是关于打字稿中 obj.prop 和 obj['prop'] 的区别?的主要内容,如果未能解决你的问题,请参考以下文章

将 Linq 表达式“obj => obj.Prop”转换为“parent => parent.obj.Prop”

将 Linq 表达式“obj => obj.Prop”转换为“parent => parent.obj.Prop”

javascript 中的 obj?.prop 语法是啥? [复制]

去除数组中值的双引号

Object.defineProperty(obj,prop,descriptor)简单使用

分别给出浅克隆和深克隆实现