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

Variables (extracted from a discriminated union object) lose narrowed types after being exported #59652

Open
laam-egg opened this issue Aug 16, 2024 · 2 comments · May be fixed by #59673
Open
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Milestone

Comments

@laam-egg
Copy link

🔎 Search Terms

discriminate union export destructure destructuring

🕗 Version & Regression Information

  • This is the behavior in every version I tried (including the nightly one), and I reviewed the FAQ for entries about (export, destructure, discriminate, union).

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABAQwhApgBygZSgJxjAHMB5MAGwE8AKAfQA8AuRAZwKOIEpEBvRAL4AoUJFgIUaLFAByIChQCCYACYBVVemBF0K8tXrNEYeRUQAfROBVadKnv2Ejw0eEgC2IKCGQKqAUTBkACMKXQAFZBh8AB4AFQA+GgA3XxB0FjiuFl4hRER0INDdFgJ0gBo8xFSKdJYZBDkFELD4hMqBCz4qwpaSxGBfVnRK-Jq641Mu61swXQ7u-JhgRBoTBUQAXm3qtPQLSxntOZUtnfH0Byr8-HRvfCR+XuKVFkGKYfLd2ozJjYEANxVTroD77XL5G53EAPPgFIphV6IMojb7pQRA-LCJwQBDsOHPREsfxfC4sABqgi2iE83l81ECfRUkWiNAARKw4O59uxCCQ0eg2VwgUJlqt-Fd8uSAYgAPSyxAAC3Qt0QMCgatYbA4JC+cAA1lVUBhsHg+WRKLRycKhCCwYtENK5Qrlar1Zq-mZDppjvNEAajVJsE0lKoNDZfXpLTRrUCnOgGJg4PgNbiwPingi-RcqZsaV4fH5GS8Wfh2ZzudrzQKhUJRSsaITdJKBTL5UqVft3TAtbzOF11l6rD67F8AO7oaIqQMm3A6i0GC7C52IfwAJTXpDXtoK9ohrZXrq7GqGcA9ff5lkH0xHJxn0hDynUt90+loS7bCvXm+3wiAA

💻 Code

function acceptStringOnly(_x: string) { }
function acceptNullAndUndefinedOnly(_x: null | undefined) { }

function mutuallyEnabledPair<T>(value: T): {
  enabled: true,
  value: NonNullable<T>,
} | {
  enabled: false,
  value: null | undefined,
} {
  if (null === value || undefined === value) {
    return { enabled: false, value: null };
  } else {
    return { enabled: true, value };
  }
}

const { enabled: E, value: V } = mutuallyEnabledPair("some string value");

if (E) {
  V; // here it is string, ok
  acceptStringOnly(V);
} else {
  V; // here it is null | undefined, ok
  acceptNullAndUndefinedOnly(V);
}

export const { enabled, value } = mutuallyEnabledPair("some string value")

if (enabled) {
  value; // here it is string | null | undefined, weird
  acceptStringOnly(value); // ERROR
} else {
  value; // here it also is string | null | undefined
  acceptNullAndUndefinedOnly(value); // ERROR
}

🙁 Actual behavior

When variables are destructured from an object of a discriminated union type and they are exported, those variables lose their narrowed types defined by the discriminated union type. Meanwhile, if the variables are NOT exported, their narrowed types will be preserved, which is the expected behavior, whether the variables are exported or not.

🙂 Expected behavior

Preserve narrowed types for variables that are:

  • Destructured from an object of a discriminated union type
  • Exported.

Additional information about the issue

I guess this issue may be more or less related to this one.

@RyanCavanaugh RyanCavanaugh added Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases labels Aug 16, 2024
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 16, 2024
@MichalMarsalek
Copy link

Simplified repro:

declare function mutuallyEnabledPair(): {
  discriminator: true,
  value: string,
} | {
  discriminator: false,
  value: null | undefined,
}

export const { discriminator, value } = mutuallyEnabledPair()

if (discriminator) {
  value;
}

@MichalMarsalek
Copy link

MichalMarsalek commented Aug 18, 2024

In the function getCandidateDiscriminantPropertyAccess, symbol.valueDeclaration is undefined in the export version & isn't undefined without the export.
This leads to the narrowing using the discriminant to not work.

#59673 Seems to fix it, altough I doubt this is a proper solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants