Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript and dot-notation access to objects

If TypeScript is a strict superset of JavaScript, why is dot notation on an arbitrary object erroneous? I have JS code that I want to convert over to TS for better type safety, but all access using dot notation (eg, myObj.thing) gives me the error Property 'thing' does not exist on type '{}'.. It works properly when I use bracket notation (eg, myObj['thing']).

Property does not exist on type

like image 696
user655321 Avatar asked May 07 '15 00:05

user655321


People also ask

How do you access object properties in TypeScript?

To dynamically access an object's property: Use keyof typeof obj as the type of the dynamic key, e.g. type ObjectKey = keyof typeof obj; . Use bracket notation to access the object's property, e.g. obj[myVar] .

What is dot notation in TypeScript?

The question mark dot (?.) syntax is called optional chaining in TypeScript and is like using dot notation to access a nested property of an object, but instead of causing an error if the reference is nullish, it short-circuits returning undefined .

What is the difference between accessing an object with dot vs with [] in JavaScript?

The dot notation is used mostly as it is easier to read and comprehend and also less verbose. The main difference between dot notation and bracket notation is that the bracket notation allows us to access object properties using variable.

Which is a valid notation for accessing object properties?

Property accessors provide access to an object's properties by using the dot notation or the bracket notation.


2 Answers

I know you say this is odd, but this is one of the main reasons TypeScript exists. This error helps prevent accidentally setting or getting non-existent properties on an object.

Right now, as the compiler is telling you, the property bar does not exist on x because it has been implicitly typed to {} when writing var x = {};.

You can tell the compiler that x has more than zero properties by explicitly defining the type:

var x: { foo?: string; bar?: string; } = {}; 

Now you can get or set x.foo and x.bar without the compiler complaining. In most cases, you would move this into an interface like so:

interface IFooBar {     foo?: string;     bar?: string; }  var x: IFooBar = {};  x.foo = "asdf";  // ok x.test = "asdf"; // error, as it should be 

Some people are recommending you cast to any, but don't get lazy. You should make full use of the type system TypeScript provides. Doing so will most definitely save you time down the road as you maintain an application.

like image 84
David Sherret Avatar answered Sep 23 '22 03:09

David Sherret


Because of the strongly-typed nature of Typescript Object, you can use "any" to make it untyped:

var x: any = {}; x.bar = "bar";   /// ok 

If what's you need is to define type of literal properties

var x: { [index: string]: TypeA } = {}; 

then x["bar"] can now only be instance of TypeA.

like image 41
Val Avatar answered Sep 23 '22 03:09

Val