Skip to content

TS7031 false positive for nested object binding pattern with = {} default in an annotated parameter (regression from #64043) #64431

Description

🔎 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions