🔎 Search Terms
TS7031, Binding element implicitly has an 'any' type, object binding pattern default, nested destructuring default, annotated parameter destructuring, padObjectLiteralType, 64043, 59920
🕗 Version & Regression Information
⏯ Playground Link
https://tsgo.sxzz.dev/#eNqtVGFr2zAQ/SuH9qEpOG6apB3zGKPbOuhgK7T9lgQq2+dERZY86Zw2hPz3neQkS9ttnwYBRb67d+89nbQWlcgmE1FLZVLyIhEnJ3CDjbMZ3N2+HYxOoZLaIzTWK1JLBGtAGmNJEpZg0IfF5g9YEOTKlMrMoZFE6IxPpyaizR16z2n5CmpVOOttRSd3qwZvC6caenM+HoxH0JuKC63m5iVaiZVsNXl4VLQA6Zxc+ak4juBdg9ZkQH5uod/35BTX9vvGXtaKwAUpLGyffPnUMDiT6ZEv4DwdpKOEBZUdQI6VdQgdo+MMjAV0zrqtlIuCWqlDKefKikXuU2Mc9v16w0EyPmOEWL61MoNPW02osUZDcJQfgaobrQpFegUL6ZkLHEmzOgJig7q2h7BnyWj4P2CVYfaVLBCujGEd66kBkB9Zclvn6N6HbX643RzWXLdBe6xRoZwTI0yXx5RPU7hVuQ6kYvfdKSZwn99DadGzt5TGnfKRVJwPWuBuvJQ1zBOfGusIqtYU4Uscgi1ybx17Z7CW8AFOE8g3vK43m6zjd9wRdEitMzCRnDDbExym8MOC33LcsgPJP63/0FZqa/B3w392yvdNPltDTnri8Qy6wugC/mzVUupwTHyq3CQ6sWAWzK8bPz7Zw+F6dlqx30VEemZ/d06TrcBX9EPBV+vqvYTJzrMZr5PZTklE/ptxYpZMBF8bayo1Tx+8NfxexNSpKGzdKI3uugkN+YKySyESYiTdHCl8mgr0TI7/J7tgbctWYxds+KFAt+Tdi/ANeqvbgNwl5q0pudlBXnfxQ5Rci/vP6L9HgKtgoG1exW1LXxTjBNBS+UNiJRZaujiHr8qYp9VL/MYWdPi7jJDA/rNVs0QUIhPs0JKX4WB4nr5Lh2PeP4osvqmbX5eN1GQ=
💻 Code
// Repro: TS7031 false positive on annotated nested object binding patterns.
// Regressed by microsoft/TypeScript#64043 ("Align object binding defaults with arrays").
//
// Run: tsgo --strict --noEmit repro.ts
//
// Expected (tsc 6.0.3, and tsgo before #64043): no errors.
// Actual (tsgo after #64043):
// repro.ts(20,45): error TS7031: Binding element 'b' implicitly has an 'any' type.
// repro.ts(25,32): error TS7031: Binding element 'b' implicitly has an 'any' type.
interface Inner {
a?: number;
b?: number;
}
interface Outer {
inner?: Inner;
}
// 1. Sibling has a default, `b` does not. `b` is typed by the annotation.
export function withSibling({inner: {a = 1, b} = {}}: Outer) {
return [a, b];
}
// 2. No sibling default at all.
export function alone({inner: {b} = {}}: Outer) {
return b;
}
// Contrast: the array equivalent reports nothing, before or after #64043.
interface OuterArray {
inner?: number[];
}
export function arrayForm({inner: [a = 1, b] = []}: OuterArray) {
return [a, b];
}
🙁 Actual behavior
tsgo reports TS7031 on the two annotated parameters:
repro.ts(20,45): error TS7031: Binding element 'b' implicitly has an 'any' type.
repro.ts(25,32): error TS7031: Binding element 'b' implicitly has an 'any' type.
b is not actually any: the Outer annotation still types it. With --declaration, tsgo emits alone({ inner: { b } }: Outer): number | undefined, which contradicts the error.
🙂 Expected behavior
No errors, matching tsc 6.0.3 and tsgo before #64043.
The array analog (arrayForm, {inner: [a = 1, b] = []}: OuterArray) is still accepted, so after #64043 annotated object patterns are stricter than annotated array patterns rather than aligned with them.
Additional information about the issue
#64043 changed padObjectLiteralType to pad every missing non-rest binding element (previously only elements with an initializer) and to call it with reportErrors=true. That's right for the unannotated case from #59920 (({required, optional = false} = {}) => {}), which is the only case the new test covers. But when the enclosing parameter has a type annotation, the = {} initializer is checked against a contextual type that already supplies the property types, so reporting implicit-any on the padded elements is spurious.
The array path doesn't hit this because a contextually typed [] isn't inferred as a tuple, so padTupleType never runs.
A possible fix: only report implicit-any from padObjectLiteralType when the binding pattern has no declared or contextual type.
We hit this while moving a large codebase to tsgo; the pattern (nested destructuring with = {} defaults in a typed parameter) is fairly common there.
🔎 Search Terms
TS7031, Binding element implicitly has an 'any' type, object binding pattern default, nested destructuring default, annotated parameter destructuring, padObjectLiteralType, 64043, 59920
🕗 Version & Regression Information
⏯ Playground Link
https://tsgo.sxzz.dev/#eNqtVGFr2zAQ/SuH9qEpOG6apB3zGKPbOuhgK7T9lgQq2+dERZY86Zw2hPz3neQkS9ttnwYBRb67d+89nbQWlcgmE1FLZVLyIhEnJ3CDjbMZ3N2+HYxOoZLaIzTWK1JLBGtAGmNJEpZg0IfF5g9YEOTKlMrMoZFE6IxPpyaizR16z2n5CmpVOOttRSd3qwZvC6caenM+HoxH0JuKC63m5iVaiZVsNXl4VLQA6Zxc+ak4juBdg9ZkQH5uod/35BTX9vvGXtaKwAUpLGyffPnUMDiT6ZEv4DwdpKOEBZUdQI6VdQgdo+MMjAV0zrqtlIuCWqlDKefKikXuU2Mc9v16w0EyPmOEWL61MoNPW02osUZDcJQfgaobrQpFegUL6ZkLHEmzOgJig7q2h7BnyWj4P2CVYfaVLBCujGEd66kBkB9Zclvn6N6HbX643RzWXLdBe6xRoZwTI0yXx5RPU7hVuQ6kYvfdKSZwn99DadGzt5TGnfKRVJwPWuBuvJQ1zBOfGusIqtYU4Uscgi1ybx17Z7CW8AFOE8g3vK43m6zjd9wRdEitMzCRnDDbExym8MOC33LcsgPJP63/0FZqa/B3w392yvdNPltDTnri8Qy6wugC/mzVUupwTHyq3CQ6sWAWzK8bPz7Zw+F6dlqx30VEemZ/d06TrcBX9EPBV+vqvYTJzrMZr5PZTklE/ptxYpZMBF8bayo1Tx+8NfxexNSpKGzdKI3uugkN+YKySyESYiTdHCl8mgr0TI7/J7tgbctWYxds+KFAt+Tdi/ANeqvbgNwl5q0pudlBXnfxQ5Rci/vP6L9HgKtgoG1exW1LXxTjBNBS+UNiJRZaujiHr8qYp9VL/MYWdPi7jJDA/rNVs0QUIhPs0JKX4WB4nr5Lh2PeP4osvqmbX5eN1GQ=
💻 Code
🙁 Actual behavior
tsgo reports TS7031 on the two annotated parameters:
bis not actuallyany: theOuterannotation still types it. With--declaration, tsgo emitsalone({ inner: { b } }: Outer): number | undefined, which contradicts the error.🙂 Expected behavior
No errors, matching tsc 6.0.3 and tsgo before #64043.
The array analog (
arrayForm,{inner: [a = 1, b] = []}: OuterArray) is still accepted, so after #64043 annotated object patterns are stricter than annotated array patterns rather than aligned with them.Additional information about the issue
#64043 changed
padObjectLiteralTypeto pad every missing non-rest binding element (previously only elements with an initializer) and to call it withreportErrors=true. That's right for the unannotated case from #59920 (({required, optional = false} = {}) => {}), which is the only case the new test covers. But when the enclosing parameter has a type annotation, the= {}initializer is checked against a contextual type that already supplies the property types, so reporting implicit-any on the padded elements is spurious.The array path doesn't hit this because a contextually typed
[]isn't inferred as a tuple, sopadTupleTypenever runs.A possible fix: only report implicit-any from
padObjectLiteralTypewhen the binding pattern has no declared or contextual type.We hit this while moving a large codebase to tsgo; the pattern (nested destructuring with
= {}defaults in a typed parameter) is fairly common there.