Skip to content

Parameter type inference/capture depends on the order of declaration of fields in an object. #56297

Closed as not planned
@MatAtBread

Description

@MatAtBread

🔎 Search Terms

parameter type inference capture
order of fields
order of declaration

🕗 Version & Regression Information

  • This changed between versions 4.6.4 and 4.7.4

In 4.6.4 is was consistently broken in that it just didn't work irrespective of the order the fields are declared. From 4.7.4 onwards it works if methods are declared before init, but not if init is declared before methods.

It remains with this inconsistent behaviour in 5.3.0-beta

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.2.2#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXxAA8MRVRgAeABQD4AKURALngG8AoeeAWxAwAscwAM4B+FlQDcneFlRYM4+HShMqASngBeGvCioAntIC+6lmgDWqHAHdU09mDzCM8ALLaCxUuTocuvAJCwiz+XPAARrB0mqzwcBjIMPgAjPDGMsYANDJyCiqxMlwJSfhQAHRRMDFcAPS1erLC8AAGcVUxLCmS6S2Z7KYOTqgu8ABynkQkZCDAfrnyGAVsRfF8pXqV0Zr1jVjNLZbWdn1c2TKBgiKhqx2xa4nJ8GkZZwPq0kA

💻 Code

declare function extended<P>(def: {
  methods?: P;
  init?: (a:P) => any;
}): unknown;

const M = extended({
  methods: {
    bar() { return 1 }
  },
  init(a) {
    return a.bar()  // a is `{ bar(): 1; }`
  }
});

const N = extended({
  init(a) {
    return a.bar() // a is `unknown`
  },
  methods: {
    bar() { return 1 }
  }
});

🙁 Actual behavior

const M works as expected.

const N has errors dereferencing a in all locations. Hovering reveals that in N, a is unknown

🙂 Expected behavior

In N.init(), a should be:

a: {
    bar(): 1;
}

...as it is in M, not unknown

Additional information about the issue

This is a heavily simplified snippet from a codebase that defines a form of class/object hierarchy.

I've never come across an issue where the order that fields are declared in an object affect how types are inferred or captured.

Any ideas where I might start looking into a fix, or a workaround (other than swapping the order in all my declarations!).

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions