-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Error when destructuring with literal initializers as fallback #26235
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
Comments
const x = options || {};
let { color, width } = x; works, so I would expect the shortened |
Should we allow |
Fair point, I concede that I was making "a principled point", while I recognize the strength of TypeScript is often in making pragmatic choices. |
Oops, wrong button. |
So can I expect Typescript 3.2.1 will not report the below snippet let { subject, topic, subTopic } = value || {}; as below error
reference: playground Since many es syntax are reported as error by typescript, we very restricted by the way we code 😞 |
A type-safe workaround you can use is |
Is this a bug though? Typescript is correctly checking that type Options = { color?: string; width?: number; };
function A({ color, width }: Options = {}) {
//
}
function B(options: Options) {
options = options || {};
let { color, width } = options;
}
function C(options: Options) {
let { color, width } = options || {} as Options;
} Better Playground link |
I believe it is a bug, clearly the B example works because TS can detect that an expression And while your solution is an obvious workaround in TS, this is more of a problem in type-checked Javascript (which is where I encountered it), where typing your function params and return values via JSDoc is more common, and much easier than typing individual expressions. |
In fact, i believe this should have the |
Ok. First, as I understand this function B(options: Options) {
options = options || {};
let { color, width } = options;
} Typescript should be correctly assuming that options will never be null, or undefined, as it shouldn't be, because you are not saying that it is optional. But, if you actually mark it as optional, then you are right, I think the bug is here: function B(options?: Options) {
const a = options || {};
let { color, width } = options;
}
In example 3, and the error case, TS is checking the typing of |
The issue seems to present itself when destructuring from a nested object as well interface Props {
innerObject?: {
name?: string;
email?: string;
};
}
// won't let name and email default to undefined
// Initializer provides no value for this binding element and the binding element has no default value.
export const nestedDestructure1 = (props: Props) => {
const { innerObject: { name, email } = {} } = props;
console.log(name, email);
};
// no errors, but is a little annoying
export const nestedDestructure2 = (props: Props) => {
const { innerObject: { name = undefined, email = undefined } = {} } = props;
console.log(name, email);
};
// no errors, but is a little annoying
export const nestedDestructure3 = (props: Props) => {
const { innerObject = {} } = props;
const { name, email } = innerObject;
console.log(name, email);
}; I'd really expect This issue has been fixed for function params with #4598, so this would work in that situation: export const nestedDestructure1 = ({innerObject: {name, email} = {}}: Props) => {
console.log(name, email);
}; |
Another simple obvious example how it's wrong: type State = {
open?: boolean;
}
class MyComponent extends React.Component<{}, State> {
render() {
const { open } = this.state || {};
~~~~
Initializer provides no value for this binding element
and the binding element has no default value.
TS2525
return <span>{open}</span>;
}
} Destructuring from Even if there's deep theoretical correctness reasoning how and why it's consistent with {whatever}, this pattern is common enough to have a hard-coded special casing. @RyanCavanaugh brought up this example: let { colour } = { color: "red" };
~~~~~~ Inconsistent British spelling of colour Which basically says TypeScript helpfully highlights undeclared members for fear of typos, which is totally reasonable! However, when destructuring from |
Although this works identical, TS will complain otherwise, see microsoft/TypeScript#26235
* chore(TS): convert geo-search util * chore(TS): migrate prepareTemplateProps * chore(TS): migrate src/lib/show-more * chore: remove src/lib/show-more apparently this isn't used! * chore(TS): refine template type * chore(TS): add correct default value Although this works identical, TS will complain otherwise, see microsoft/TypeScript#26235 * chore: use already declared Template type * chore: remove needless default value
* chore(TS): convert geo-search util * chore(TS): migrate prepareTemplateProps * chore(TS): migrate src/lib/show-more * chore: remove src/lib/show-more apparently this isn't used! * chore(TS): refine template type * chore(TS): add correct default value Although this works identical, TS will complain otherwise, see microsoft/TypeScript#26235 * chore: use already declared Template type * chore: remove needless default value
I have this problem with typescript 4. |
I think this is the simplest solution, did the same on my project. |
Ran into this when upgrading from TS 4.4 to 4.6.
I was able to resolve the
Seems like a bug to me. |
Still an issue in |
Please log a new bug if you think you have found an issue; maintainers are not necessarily reading comments on 5-year-old closed issues |
Uh oh!
There was an error while loading. Please reload this page.
TypeScript Version: 3.0.1
Destructuring with a fallback empty object literal is a common practice, especially in function arguments (which works), but not always:
Code
Expected behavior: All three functions type-check and behave the same.
Actual behavior: "Initializer provides no value for this binding element" Error.
Which is simply incorrect, ES spec clearly defines the value when an object key is missing as
undefined
. Furthermore, I would argue TS should even acceptlet { color } = {};
though it's obviously not as common/important.Related Issues:
Issue #4598 - Improved checking of destructuring with literal initializers fixed the same problem, but only for destructuring function arguments (example A).
Playground Link: here
The text was updated successfully, but these errors were encountered: