Skip to content

TypeScript doesn't assume the value type in a ternary operator when it has been assigned before if the value is an object keyΒ #50356

Closed

Description

Bug Report

πŸ”Ž Search Terms

ternary operator, props object, object is possibly null

πŸ•— Version & Regression Information

  • This happens in version 4.7.4 and 4.8.0-beta

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type Props = {
  value: string | Array<string> | [] | null;
};

function example1(props: Props) {
  const isValueAnArray = Array.isArray(props.value);
  const isValueEmpty = !(isValueAnArray ? !!props.value.length : !!props.value);
                                                       ^ (property) value: string | string[] | [] | null
                                                          Object is possibly 'null'.
}

function example2(props: Props) {
  const isValueAnArray = Array.isArray(props.value);
  const isValueEmpty = !(Array.isArray(props.value) ? !!props.value.length : !!props.value); // No errors
}

function example3(value: string | Array<string> | [] | null) {
  const isValueAnArray = Array.isArray(value);
  const isValueEmpty = !(Array.isArray(value) ? !!value.length : !!value); // No errors
}

πŸ™ Actual behavior

example1 throws an error because TS thinks props.value might be null when checking its length.

πŸ™‚ Expected behavior

There should be no error, like in the other two functions.

Activity

  1. whzx5byb commented on Aug 18, 2022

    @whzx5byb

    From #44730:

    Narrowing through indirect references occurs only when the conditional expression or discriminant property access is declared in a const variable declaration with no type annotation, and the reference being narrowed is a const variable, a readonly property, or a parameter for which there are no assignments in the function body.

    So you have to mark the property value readonly to make it work:

    type Props = {
    -  value: string | Array<string> | [] | null;
    +  readonly value: string | Array<string> | [] | null;
    };
  2. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions