Home > Back-end >  Difference between obj.prop and obj['prop'] in typescript?
Difference between obj.prop and obj['prop'] in typescript?

Time:12-20

After using @babel/parser to parse some string and getting a ast, I encouter an error when logging the ast by the type of obj.prop, but it work when use the type of 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);

I'm confused about the difference of the two type writing?

thanks for answer

CodePudding user response:

You can access the properties of an object in JavaScript/typescript :

  1. Dot property accessor: object.property
  2. Square brackets property access: object['property']

When to use :

Choose the dot property accessor when the property name is known ahead of time.

eg.

const hero = {
  name: 'XYZ'
};

Here property is already known ahead of time so we can use hero.name

Choose the square brackets property accessor when the property name is dynamic, i.e. determined at runtime.

eg :

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

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

Here the property is detemined at runtime so we user square brackets.

So if you use the property dot accessor on the property which is determined at runtime time typescript will give you error

Property 'name' does not exist on type hero.

There are no good or bad ways to access properties. Choose depending on your particular situation.

Hope this clear object property accessor.

CodePudding user response:

You can access a property in typescript with either dot notation or bracket notation. There is a difference between the two with regards to errors though, depending on compiler options.

If you set noImplictAny to false (which is the default), you will not get an error with bracket notation even if the property can't be compile time checked to be valid, you just get an implicit any. So ast.program.body[0]["declaration"] will be any, and typescript won't check the .properties that comes after. Playground Link

If you set noImplictAny to true, typescript will complain about not being able to check that declaration is indeed a property of ast.program.body[0] and you will get errors for both (admittedly, slightly different errors) Playground Link

You probably want to do some narrowing of the type of ast.program.body[0] before you access it's members. Here would be a way to narrow ast.program.body[0] to an expression statement and then to an object expression which does have a properties member:

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

NOTE: I changed {key: "something"} to ({key: "something"}). I assumed you are trying to parse an object literal. Your version was actually a block statement with a labeled statement inside. Block statement vs Object literal

  • Related