microsoft / microsoft/TypeScript

this type in conditional type false clause is incorrectly typed

Open
#36,005 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Domain: This-Typing
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

TypeScript Version: 3.7.3

Search Terms:
generic type this widening incorrect

Code

type Option1 = { run(this: { b: 1 }): void }

function f1(options: Option1) { return options }

// `this` is correctly typed as `{ b: 1 }`
f1({ run() { this.b } })

type Option2<Config> = Config extends Record<string, any> ? {
  config: Config,
  run(this: Config): void
} : {
  run(arg: { b: 1 }): void
}

function f2<Config>(options: Option2<Config>) { return options }

// `this` is correctly typed as `{ a: number }`
f2({ config: { a: 1 }, run() { this.a } })
// `arg` is correctly typed as `{ b: 1 }`
f2({ run(arg) { arg.b } })

type Option3<Config> = Config extends Record<string, any> ? {
  config: Config,
  run(this: Config): void
} : {
  run(this: { b: 1 }): void
}

function f3<Config>(options: Option3<Config>) { return options }

// `this` is correctly typed as `{ a: number }`
f3({ config: { a: 1 }, run() { this.a } })
// `this` is widen to what `Config` extends to. In this case `Record<string, any>`
f3({ run() { this.b } })

Expected behavior:
this in f3({ run() { this.b } }) should be typed as in this in f1() and arg in f2()

Actual behavior:
this in f3({ run() { this.b } }) is typed as the base type of Config (Record<string,any> in the example above)

Playground Link:
Playground Link

Related Issues:
Some maybe related issues:
https://github.com/microsoft/TypeScript/issues/32990
https://github.com/microsoft/TypeScript/issues/30152
https://github.com/microsoft/TypeScript/issues/13995

I also recall there were some discussion about type and Record<>, but that is in the gitter channel and I can't find relevant issue or doc about it.

I think this is different than the related issues above because this does not involve union type.

This is about the false condition of the conditional type Config extends Record<string, any> ? ... : ... do not use the generic type Config and should not be affected by it.

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

Reproduce the examples in the linked TypeScript Playground, comparing the contextual type of this in f1, f2, and f3. Investigate conditional-type contextual typing for the false clause; done means the f3 callback's this is typed as { b: 1 } rather than the widened base type, without regressing the other examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.