Why does accessing a property of indexOf still compile?

2k views Asked by At

I made a typo in TypeScript which was picked up during code review.

I used someArray.indexOf[someObject] instead of someArray.indexOf(someObject).

I would expect an error from the IDE/Compiler. Instead, no errors were raised and the result was simply undefined.

Can anyone explain this?

4

There are 4 answers

4
sjahan On BEST ANSWER

Quite easy.

someArray.indexOf you know that this is a function, which is also an object and can have properties.

By doing someArray.indexOf[someObject], you are trying to reach the property with the key valued to the value of someObject.

Of course, it is not defined on the indexOf function, so it returns undefined.

Quick example that illustrates the syntax and the fact that a function can have properties ;) :

const array = [];
array.indexOf['anyValue'] = 'test';
console.log(array.indexOf.anyValue);

EDIT

Here is an attempt of an answer for the TypeScript side of the question.

As you already know, TypeScript is designed to be compatible with JavaScript. Therefore, as in JS, you can access a property of an object by the following ways:

  • 'Statically': obj.property
  • 'Dynamically': obj['property']

By using the 'static' way to access a property, of course, TypeScript will raise an error!

But with the dynamic way of accessing the property, there is no way TypeScript compiler can determine the type of it or if it exists or not, since the value between bracket will be evaluated at runtime, after TypeScript transpiling.

That's why it will be implicitly marked as any.

As David Sherret mentioned in his answer, you can force TypeScript to raise an error by adding the flag --noImplicitAny, please refer to his answer for more details about this!

Hoping this helps ;)

0
David Sherret On

It does not error because the --noImplicitAny compiler option is not enabled. With that compiler option enabled you will get an error as expected:

noImplicitAny enabled

The reason is that an element access expression returns an object typed as any when the type has no index signature defined (this is an implicit any).

enter image description here

So again, since --noImplicitAny is not enabled, it does not error. I highly recommend turning this compiler option on.

1
Alex Steinberg On

The only real issue here is that you expected Typescript to throw an error that exposed the problem in your logic. The intended logic was to use curly braces and utilise the someArray.indexOf(someObject) function.

What happened when you used square braces, someArray.indexOf[someObject], was that the JS runtime first converted your object someObject into a string by calling the function someObject.toString, which most likely returned "[object object]". Then the someArray.indexOf object was queried for the key "[object object]" which wasn't present, returning undefined. As far as Typescript goes, this is completely fine.

David Sherret pointed out that --noImplicitAny would have pointed out the error, but it would only have pointed out a different error, as he explained, which would not directly have helped you to find the flaw in your logic.

2
0xc14m1z On

array.indexOf is a function.

Functions are objects.

You were accessing the someObject property of the array.indexOf function.

You would have got undefined.

const array = [1, 2, 3]
const someObject = 'asdasd'

console.log(array.indexOf[someObject])
// undefined