-2

There is no way that this code fails

const fn = (obj: object) => obj?.prop;

but the TypeScript compiler prevents me from writing that, explaining that

Property 'prop' does not exist on type 'object'

but that's precisely the use of optional chaining: if the property exists, I access it, else I access undefined, and it works on any object. So why does TS doesn't let me write this and is there a setting in my tsconfig.json I can set so that I can write that?

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
  • 1
    That's not what optional chaining is. Optional chaining checks if `obj` is null, not if the property to the right exists (`prop`). – Connor Low Sep 07 '21 at 16:42
  • Well yeah but that won't ever make the code fail because `({}).prop` is valid JS that doesn't throw a `TypeError` – Nino Filiu Sep 07 '21 at 16:47
  • There are many things that are valid in JS that are unacceptable in TS; that is very intentional. If all you want is type-hinting, you might check out JS docs instead (e.g., [VS Code](https://code.visualstudio.com/docs/languages/javascript#_type-checking)). It's a nice balance of familiar JS with better IntelliSense and no additional compiling. – Connor Low Sep 07 '21 at 17:01

1 Answers1

1

From Mozilla:

The optional chaining operator (?.) enables you to read the value of a property located deep within a chain of connected objects without having to check that each reference in the chain is valid.

In your case, obj is the reference being checked for null or undefined, not prop.


So why does TS doesn't let me write this

You've told TS to expect an object, but you have not told TS anything about the properties of that object, so it has no idea if prop exists. In other words, prop is not on the interface of object, so it throws a compiler error.


is there a setting in my tsconfig.json I can set so that I can write that?

The behavior from above is the whole point of TypeScript, a static type checker. You do not want this exact behavior to be enabled, but there is an intended way within the language to produce the same effect:

const fn2 = (obj: Record<string, any>) => obj.prop;

The above code requires that obj be non-null/undefined and allows for any string (or number, but not Symbol) property accessor.

Playground

Connor Low
  • 5,900
  • 3
  • 31
  • 52