Skip to content

Error 2339 with nullish coalescing to empty objectΒ #51665

Description

@KuSh

Bug Report

πŸ”Ž Search Terms

2339 Property does not exist on type empty object

πŸ•— Version & Regression Information

Tested on 4.2.3 (version we use on our project) and 4.8.4 (latest available in playground)

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

const ok = (): null | { [param: string]: string } => Math.random() > .5 ? null : {};
const ko = (): null | { uri: string; path: string; [param: string]: string } => Math.random() > .5 ? null : { uri: '', path: '' };

{
    // no errors
    const { oid, pid } = ok() ?? {};
}

{
    // error 2339 - Property does not exist on type '{ [param: string]: string; uri: string; path: string; } | {}'
    const { oid, pid } = ko() ?? {};
}

This is a simplified test case. I did encounter error while using @reach/router useMatch hook API

πŸ™ Actual behavior

Error Property does not exist on type '{ [param: string]: string; uri: string; path: string; } | {}' (2339)

πŸ™‚ Expected behavior

No error expected

Activity

  1. SquareByte commented on May 24, 2023

    @SquareByte

    After replacing the ?? operator with older-style code I still get an error (TS4.9.5):

    const ko_result = ko();
    const assert_some_obj = ko_result === null ? {} : ko_result; // same for `ko_result || {}`
    const { oid, pid } = assert_some_obj;
    // Property 'pid' does not exist on type '{}'. ts(2339)

    This is correct, isn't it?

    With the same rewrite this also gives no error in the case of the ok() function though. But I'd rather expect an error in both cases and ideally with the union type boiled down to the second union member:

    πŸ™‚ Expected behavior

    Error Property does not exist on type '{}' (2339) in both examples.


    PS:

    const { pid } = {};
    // Initializer provides no value for this binding element and the binding element has no default value. ts(2525)
    // Binding element 'pid' implicitly has an 'any' type. ts(7031)

    So this does not look like fully sane code anyway.

  2. kirkwaiblinger commented on Sep 9, 2024

    @kirkwaiblinger

    Note that there is a pretty organic repro occurring with regexp parsing:

    const re = /.*/;
    const str = "matched";
    
    const result = re.exec(str);
    if (result != null) {
        const { namedGroup } = result.groups ?? {};
        console.log(namedGroup.toLowerCase()); // runtime error!
    }

    (playground link)

  3. kirkwaiblinger commented on Sep 9, 2024

    @kirkwaiblinger

    (for a more minimal repro)

    // this issue is specifically triggered by index signatures
    declare const maybeIndexable: { [key: string]: string} | undefined
    const { anyThing } = maybeIndexable ?? {};
    console.log(anyThing.toLowerCase()); // runtime error!
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

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions