microsoft / microsoft/TypeScript

Error span incorrect when `this` constraint on member function fails

Open
#60,709 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Domain: Related Error Spans Help Wanted Possible Improvement
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 Search Terms
  • error span
  • this: never
  • this chain
  • builder pattern
🕗 Version & Regression Information
  • This is the behavior in every version I tried (including the latest 5.7.2)
⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241206#code/PQKhCgAIUhZBTAtgI3gJ0gMwK4DsDGALgJYD2ukyAhgM7wAmk+t8UIw4+ANrTZAGJ4iZXACEW9UdmJd66ADwBlQvAAOkeAA8Vuen1zYU6ALwBGAHyQA3lEg0Vq0wApCAC2I0AXJGVqN2+F0+U0gAfkg3D0hvXHgAN3QASm9BAhJycTpJaVkFACZLG0hiyDR4Qmw0Cki+WkgqXABPAG5bAF9bezU8l3cvHwd-HT1IPLCIvujIWIS0ZIEhdLEJKRk5NHkAZkLbYrKKqomouoaW9ttgYDsAa2J1LvVN-1UuYnxiQi5GiNJIOURyPY0FQVBN4Bo0GhSGhOg4ACy9DzeXzqLTDPhw8Y1KYzJIpRYiTIMVa5DYAVh2JVK5Uq1UmJyarWKHQ64FAEGgcCQqAwcSoaGIVGQXHB1CyTBYbA43F4kAAavzBcL4ETsmsFCihoERgYjGgzJS7A5TN4nJq0drguMnIlIMZLAqBUKRaqSet5AUcfEknbIE4bXbDXsaYdsQyzszbeGmUbuqbzQEgqNrbb7fLFc6VSscu7tl7Zqm-QG00USvtaUdarVGe0o9WI5BLjc7rHHs9Xu9Pt9CL9-oDCMDQW5wegoTDig84fHBhak5jwsWHRnla6cwoKfmfcYi6mg9SDnTjvWY206-Ua6z8P2sEI3ehfbEAO4LNKE7PqtA21pNqhcLiQUhMEgAADTBSFIAA6B5nESKCHB6RJgIiWk+GIXAe3PSA8FceAuFUHB-1HaFIEQeAaBoKgAHNWBwAg7zQOC1BgxjVAQliEUSVpOGvPk0Hoh94GfR0lRdd9SS-NkrmHCEx0gVQoVUdAvnqVRFP5PhyGU8hW0gOFwF4+iWOYh42MnL8gA

💻 Code
/**
 * Member function based case
 */
class FunctionBasedBuilder<Step extends number=1> {
  step1(this: Step extends 1 ? this : never): FunctionBasedBuilder<2> {
    return this as any;
  }
  step2(this: Step extends 2 ? this : never): FunctionBasedBuilder<3> {
    return this as any;
  }
  // skip step 3 explicitly to demonstrate the error
  step4(this: Step extends 4 ? this : never): FunctionBasedBuilder<5> {
    return this as any;
  }
}

/**
 * Member variable based case
 */
class VariableBasedBuilder<Step extends number=1> {
  step1: (Step extends 1 ? () => VariableBasedBuilder<2> : never) = (() => {
    return this as any;
  }) as any;
  step2: (Step extends 2 ? () => VariableBasedBuilder<3> : never) = (() => {
    return this as any;
  }) as any;
  // skip step 3 explicitly to demonstrate the error
  step4: (Step extends 4 ? () => VariableBasedBuilder<5> : never) = (() => {
    return this as any;
  }) as any;
}

const funcBuilder = new FunctionBasedBuilder();
// all of `foo.step1().step2()` turns into an unhelpful error message
funcBuilder.step1().step2().step4();

const varBuilder = new VariableBasedBuilder();
// the error properly appears only on step 4
varBuilder.step1().step2().step4();
🙁 Actual behavior

In the function case, the entire span from foo.step1().step2() gets marked as an error instead of only step4() which is what actually caused the error

🙂 Expected behavior

Just like in the member variable case, it would be better if the error was shown on step4()

Additional information about the issue

I think this ends up being equivalent to #28159 so I'm not sure it can be solved without introducing the "curse" mentioned in #60140

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Open the linked TypeScript Playground and compare the function-based and variable-based builder cases, focusing on the diagnostic span for the final step4 call. Review the possible relationship to issues #28159 and #60140. Done means the function-based case highlights only step4(), matching the variable-based case, without regressing the reported error.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.