Skip to content
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

Angular - optional chaining not working with Signal object with optional property, #56418

Closed
dreamstar-enterprises opened this issue Jun 12, 2024 · 2 comments

Comments

@dreamstar-enterprises
Copy link

dreamstar-enterprises commented Jun 12, 2024

Which @angular/* package(s) are the source of the bug?

common, core

Is this a regression?

Yes

Description

This works:

    @if(user().contracts; as contracts) {
        @if(contracts?.length > 0) {
          <p class="contract-info">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" data-supported-dps="24x24" fill="red" class="contract-svg" width="24" height="24" focusable="false">
              <path d="M13 13h5v1h-5zm5-5H6v3h12zm-5 8h5v-1h-5zm9-12v13a3 3 0 01-3 3H5a3 3 0 01-3-3V4zm-2 2H4v11a1 1 0 001 1h14a1 1 0 001-1zm-9 7H6v3h5z"></path>
            </svg>
            {{ contracts?.length }}  @if(contracts?.length == 1) { contract } @else { contracts }
          </p>
        }
      }

But this keeps giving NG2 - Object is possibly undefined:

@if(user(); as user) {
    @if(user.contracts?.length > 0) {
      <p class="contract-info">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" data-supported-dps="24x24" fill="red" class="contract-svg" width="24" height="24" focusable="false">
          <path d="M13 13h5v1h-5zm5-5H6v3h12zm-5 8h5v-1h-5zm9-12v13a3 3 0 01-3 3H5a3 3 0 01-3-3V4zm-2 2H4v11a1 1 0 001 1h14a1 1 0 001-1zm-9 7H6v3h5z"></path>
        </svg>
        {{ user.contracts?.length }}  @if(user.contracts?.length == 1) { contract } @else { contracts }
      </p>
    }
  }

User is a simple object:

export interface UserDTO {
  _id?: string,
  dtoType: UserTypes.USER,
  contracts?: Array<AnyContractDTO>,
}

Please provide a link to a minimal reproduction of the bug

See above simple code

Please provide the exception or error you saw

keep getting NG2 - Object is possibly undefined:

Please provide the environment you discovered this bug in (run ng version)

"typescript": "^5.4.5"
    "@angular/common": "^17.3.2",
    "@angular/compiler": "^17.3.2",
    "@angular/core": "^17.3.2",

Anything else?

``

@alxhub
Copy link
Member

alxhub commented Jun 12, 2024

Without an actually runnable reproduction it's impossible to verify, but it looks to me like the type-checking error is correct per your types. user.contracts.length > 0 is not a safe expression to execute since user.contracts is potentially undefined (declared optional: contracts?: Array<AnyContractDTO>), and nothing guards its access.

@alxhub alxhub closed this as not planned Won't fix, can't repro, duplicate, stale Jun 12, 2024
@dreamstar-enterprises
Copy link
Author

dreamstar-enterprises commented Jun 13, 2024

I tried again. - it definitely doesn't work

This doesn't work

        @if(user().contracts && user().contracts?.length > 0) {
          <p class="contract-info">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" data-supported-dps="24x24" fill="red" class="contract-svg" width="24" height="24" focusable="false">
              <path d="M13 13h5v1h-5zm5-5H6v3h12zm-5 8h5v-1h-5zm9-12v13a3 3 0 01-3 3H5a3 3 0 01-3-3V4zm-2 2H4v11a1 1 0 001 1h14a1 1 0 001-1zm-9 7H6v3h5z"></path>
            </svg>
            {{ user().contracts?.length }}  @if(user().contracts?.length == 1) { contract } @else { contracts }
          </p>
        }

Neither does this:

        @if(user().contracts && user().contracts.length > 0) {
          <p class="contract-info">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" data-supported-dps="24x24" fill="red" class="contract-svg" width="24" height="24" focusable="false">
              <path d="M13 13h5v1h-5zm5-5H6v3h12zm-5 8h5v-1h-5zm9-12v13a3 3 0 01-3 3H5a3 3 0 01-3-3V4zm-2 2H4v11a1 1 0 001 1h14a1 1 0 001-1zm-9 7H6v3h5z"></path>
            </svg>
            {{ user().contracts?.length }}  @if(user().contracts?.length == 1) { contract } @else { contracts }
          </p>
        }

But this does:

@if(user().contracts; as contracts) {
        @if(contracts && contracts.length > 0) {
          <p class="contract-info">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" data-supported-dps="24x24" fill="red" class="contract-svg" width="24" height="24" focusable="false">
              <path d="M13 13h5v1h-5zm5-5H6v3h12zm-5 8h5v-1h-5zm9-12v13a3 3 0 01-3 3H5a3 3 0 01-3-3V4zm-2 2H4v11a1 1 0 001 1h14a1 1 0 001-1zm-9 7H6v3h5z"></path>
            </svg>
            {{ contracts?.length }}  @if(contracts?.length == 1) { contract } @else { contracts }
          </p>
        }
      }

If I do:

contracts && contracts?.length > 0

It fails, bizarrely. (same object undefined message)

Screenshot 2024-06-13 at 07 44 50

I think this is a typescript issue, as it's not doing a smart casting of the second condition against the '>' check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants