【问题标题】:Difference between obj.prop and obj['prop'] in typescript?打字稿中 obj.prop 和 obj['prop'] 的区别?
【发布时间】:2023-03-18 06:34:01
【问题描述】:

在使用@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);

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

感谢回答

【问题讨论】:

    标签: typescript object babeljs


    【解决方案1】:

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

    1. 点属性访问器:object.property
    2. 方括号属性访问: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,并且打字稿不会检查后面的.propertiesPlayground 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 statementObject literal

    【讨论】:

      猜你喜欢
      • 2016-08-13
      • 1970-01-01
      • 2012-11-06
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 2021-07-29
      相关资源
      最近更新 更多