Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.2.0-rc] .bind with overloads causes compile error in strict mode (strictBindCallApply) #28582

Closed
eamodio opened this issue Nov 16, 2018 · 3 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue

Comments

@eamodio
Copy link

eamodio commented Nov 16, 2018

TypeScript Version: 3.2.0-rc

Search Terms:
strictBindCallApply, bind, overload

Code

class Logger {
  static debug(message: string, ...params: any[]): void;
  static debug(context: object | undefined, message: string, ...params: any[]): void;
  static debug(contextOrMessage: object | string | undefined, ...params: any[]): void {
    // ...
  }

  static log(message: string, ...params: any[]): void;
  static log(context: object | undefined, message: string, ...params: any[]): void;
  static log(contextOrMessage: object | string | undefined, ...params: any[]): void {
    // ...
  }
}

// @log decorator
function log(debug: boolean) {
  // ...
  const logFn = debug ? Logger.debug.bind(Logger) : Logger.log.bind(Logger);

  // ...

  // Errors with Argument of type 'string' is not assignable to parameter of type 'object | undefined'
  // NOTE: This doesn't error without the .bind() call above
  logFn("message", 1, 2, 3);
}

Expected behavior:

Not exactly sure, but not an error

Actual behavior:

Error -- see playground link

Playground Link:

http://www.typescriptlang.org/play/index.html#src=class%20Logger%20%7B%0D%0A%20%20static%20debug(message%3A%20string%2C%20...params%3A%20any%5B%5D)%3A%20void%3B%0D%0A%20%20static%20debug(context%3A%20object%20%7C%20undefined%2C%20message%3A%20string%2C%20...params%3A%20any%5B%5D)%3A%20void%3B%0D%0A%20%20static%20debug(contextOrMessage%3A%20object%20%7C%20string%20%7C%20undefined%2C%20...params%3A%20any%5B%5D)%3A%20void%20%7B%0D%0A%20%20%20%20%2F%2F%20...%0D%0A%20%20%7D%0D%0A%0D%0A%20%20static%20log(message%3A%20string%2C%20...params%3A%20any%5B%5D)%3A%20void%3B%0D%0A%20%20static%20log(context%3A%20object%20%7C%20undefined%2C%20message%3A%20string%2C%20...params%3A%20any%5B%5D)%3A%20void%3B%0D%0A%20%20static%20log(contextOrMessage%3A%20object%20%7C%20string%20%7C%20undefined%2C%20...params%3A%20any%5B%5D)%3A%20void%20%7B%0D%0A%20%20%20%20%2F%2F%20...%0D%0A%20%20%7D%0D%0A%7D%0D%0A%0D%0A%2F%2F%20%40log%20decorator%0D%0Afunction%20log(debug%3A%20boolean)%20%7B%0D%0A%20%20%2F%2F%20...%0D%0A%20%20const%20logFn%20%3D%20debug%20%3F%20Logger.debug.bind(Logger)%20%3A%20Logger.log.bind(Logger)%3B%0D%0A%0D%0A%20%20%2F%2F%20...%0D%0A%0D%0A%20%20%2F%2F%20Errors%20with%20Argument%20of%20type%20'string'%20is%20not%20assignable%20to%20parameter%20of%20type%20'object%20%7C%20undefined'%0D%0A%20%20%2F%2F%20NOTE%3A%20This%20doesn't%20error%20without%20the%20.bind()%20call%20above%0D%0A%20%20logFn(%22message%22%2C%201%2C%202%2C%203)%3B%0D%0A%7D

Related Issues:
#28567

@weswigham weswigham added the Bug A bug in TypeScript label Nov 19, 2018
@ahejlsberg
Copy link
Member

This is a known (and somewhat unfortunate) limitation of --strictBindCallApply. The stricter checking looses fidelity on generic or overloaded functions. See comment here. Specifically, for overloaded functions we always pick the last overload.

@DanielRosenwasser Reminder that we should document these limitations in the blog post for the final release.

@ahejlsberg
Copy link
Member

@eamodio In terms of workarounds for this issue, you can (a) turn off --strictBindCallApply, (b) swap the overloads, or (c) use a type assertion:

const logFn = (debug ? Logger.debug.bind(Logger) : Logger.log.bind(Logger)) as typeof Logger.log;

@eamodio
Copy link
Author

eamodio commented Nov 19, 2018

@ahejlsberg Thanks for the reply! I opted for the type assertion and to be the safest I used the following to catch if one of the methods changes signature out of sync with the other.

const logFn = (debug ? Logger.debug.bind(Logger) : Logger.log.bind(Logger)) as (typeof Logger.debug | typeof Logger.log);

@DanielRosenwasser DanielRosenwasser added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Bug A bug in TypeScript labels Nov 28, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Dec 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants