microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.1k stars 12.37k forks source link

Union of functions with typed `this`, fails with no parameters #41213

Open reggi opened 3 years ago

reggi commented 3 years ago

TypeScript Version: 4.0.2

Code

interface Context {
  hello: boolean
}

type OptionsTest =
      | ((this: Context) => void)
      | ((this: Context) => PromiseLike<any>)
      | ((this: Context, done: boolean) => void)

function container (test: OptionsTest) {

}

// This does not work!

container(function () {
  console.log(this.hello);
})

// This works!

container(function (done) {
  console.log(this.hello);
})

// This works!

type Single = (this: Context) => void;
function SingleContainer (test: Single) {}
SingleContainer(function () {
  console.log(this.hello)
})

Expected behavior:

Correctly provide this type to (typed union) functions without arguments.

Actual behavior:

No this type is being provided for functions without arguments.

Playground Link

StackOverflow Link

Search Terms

denismaxim0v commented 3 years ago

I can look into that

Zzzen commented 3 years ago

I'm afraid it's working as intended. For example, CB is assignable to OverloadA and OverloadC (it’s always legal to provide a callback that accepts fewer arguments). And parameters of OverloadA and OverloadC are different so the type checker cannot determine the type of CB. Ref: https://github.com/microsoft/TypeScript/blob/6643d973856d89ef9f2e85e46fe5e460503ff256/tests/cases/conformance/expressions/contextualTyping/functionExpressionContextualTyping1.ts#L39

interface Context {
  hello: boolean
}

type OverloadA = ((this: Context) => void);
type OverloadB = ((this: Context) => PromiseLike<any>)
type OverloadC = ((this: Context, done: boolean) => void)

type OptionsTest = OverloadA | OverloadB | OverloadC;

function container (test: OptionsTest) {}

container(function CB() {
  console.log(this.hello);
})
Zzzen commented 3 years ago

possible related to https://github.com/microsoft/TypeScript/issues/37580