Skip to content

Default destructuring object not recognized properly. #52049

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
fresheneesz opened this issue Dec 30, 2022 · 6 comments
Closed

Default destructuring object not recognized properly. #52049

fresheneesz opened this issue Dec 30, 2022 · 6 comments
Labels
Duplicate An existing issue was already created

Comments

@fresheneesz
Copy link

Bug Report

🔎 Search Terms

destrucruting, object, default, empty

🕗 Version & Regression Information

Version 4.9.4

⏯ Playground Link

https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMAFAbwB6ILyIIwC+AXIpiWCALYBGApgE4E6kECUpAUIt4vbVCHpIMHAkA

💻 Code

function f({x = 1}: {x: number} = {}) {
    return x
}

🙁 Actual behavior

Property 'x' is missing in type '{}' but required in type '{ x: number; }'

This is wrong because calling, for example, f() will result in x being 1, even tho the = {} default definition is empty (because the destructuring object has a default).

🙂 Expected behavior

I would expect this to pass type linting.

@fresheneesz
Copy link
Author

Note that this is the best DRY way to define this in javascript. If you leave out the = {} then f() will result in an error (x not defined). If you instead define this as function f({x} = {x: 1} then calling f({}) will result in x not defined as well. The above is the shortest way to defined it so that both f() and f({}) can be called without issue.

@MartinJohns
Copy link
Contributor

Duplicate of #51179.

@fresheneesz
Copy link
Author

fresheneesz commented Dec 30, 2022

Ah I see, the correct way of writing this is:

function f({x = 1}: {x?: number} = {}) {
    return x
}

I assume this is because the type {x:? number} here is defining what argument type can be passed in rather than defining what parameter type is received. This is a rather awkward situation. It seems that typescript does recognize the fact that the parameter has a different type than the argument, and properly recognizes that the parameter is not in fact optional.

@fatcerberus
Copy link

Yeah, for destructurings, the type annotation specifies what kind of values can be used to initialize it, not what types the bindings will ultimately have. It usually happens to be that these are the exact same type, except for the case where one or more of the bindings has a default.

The way to think about it is that you’re annotating the imaginary temp variable used to destructure the object. It’s a bit weird IMO, but that’s how they chose to design it.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jan 5, 2023
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jan 5, 2023

Yeah, among equal desugarings to choose from, TS treats this as

function f(_obj: {x: number} = {}) { // <- type violation
    let x = _obj.x === undefined ? 1 : _obj.x;
    return x;
}

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants