Skip to content

Typescript does not identify when a property can be undefined due to a safe operator being used #56608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
joel-thompson opened this issue Nov 29, 2023 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@joel-thompson
Copy link

πŸ”Ž Search Terms

"safe navigation operator", "optional chaining"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about our issue.

⏯ Playground Link

https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgPICMBWyDeAoZZABzijgFsAuZAZzClAHMBuPAXzzzAE8iUNMqKADkA9mGQBeNFmQAfZAFcQAEwgxQEFazwAbCBJijR1AULFgdCUSBqj9AOl2jGACiOiA-A5JlyASmZkAHpg5B4+GgQGIgkAaxBRAHcacIALOAlfCmRrRV0VZHQUOgYQRmRRKCVVdU1CtOgIBwc8a1t7Zuc3D29s8gcaXWAkV39AkLCIiCiYiRo00XzC63IiXThQZEaoCAAaYlIc8jhuIpRlNQ0QLWQ4VWREiThaeiYHIA

πŸ’» Code

interface Obj {
  param: string;
}

type ObjOrNot = Obj | undefined;

let foo: ObjOrNot;

console.log(foo?.param); // typescript knows that param could be string or undefined here.
console.log(foo?.param.slice()); // typescript should complain here, param may be undefined and not a string, but it says it is a string.

πŸ™ Actual behavior

typescript allows .slice() to be called on param

πŸ™‚ Expected behavior

typescript should give an error when calling .slice() on param because param may be undefined because of the safe navigation operator before it.

Additional information about the issue

Seems related to but still a bit different from this issue: #53872

@MartinJohns
Copy link
Contributor

When foo is undefined, then the entire right side expression won't be called. That means param.slice() is never evaluated.

Try running your playground. It works just fine, even when foo is undefined.

@fatcerberus
Copy link

fatcerberus commented Nov 29, 2023

typescript knows that param could be string or undefined here.

Correction: It knows that the whole expression foo?.param can be string or undefined. However, ?. is short-circuiting so if foo is defined, foo.param is always a string, per the types. If foo is nullish then foo?.param.slice() doesn't even get evaluated.

edit: ninja'd πŸ₯·

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Nov 29, 2023
@RyanCavanaugh
Copy link
Member

The behavior of ?. is admittedly counterintuitive; the expression a?.b.c is not the same as (a?.b).c

Regardless, TypeScript accurately models the runtime behavior here.

@joel-thompson
Copy link
Author

interesting, apologies for mix up. I could have sworn I've run into issues around Cannot read properties of undefined similar to my example, but I can't reproduce it now so it must have been something else!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants