Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

170
Vistas
Bluebird / Typescript Error: 'this' context of is not assignable to method's 'this'

I have a series of methods (some asynchronous and some not) that I would like to use bluebird.each to process in order. Here is a dumbed down example:

import bluebird from 'bluebird';

const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
class Template {
  propertyA!: number;
  propertyB!: number;
  constructor() {}
  async methodA() {
    this.propertyA = 10;
    console.log({ thisArgInA: this, propertyA: this.propertyA });
    await delay(500);
    return this.propertyA;
  }
  methodB() {
    this.propertyB = this.propertyA * 100;
    console.log({ thisArgInB: this, propertyB: this.propertyB });
    return this.propertyB;
  }
}

const instance = new Template();

const sequence = [instance.methodA, instance.methodB];

(async function main() {
  await bluebird.each(sequence, (fn) => {
    const result = fn.call(instance);
    console.log({ result });
  });
})();

This produces this error I do not understand:

index.ts:27:20 - error TS2684: The 'this' context of type '(() => Promise<number>) | (() => number)' is not assignable to method's 'this' of type '(this: Template) => Promise<number>'.
  Type '() => number' is not assignable to type '(this: Template) => Promise<number>'.
    Type 'number' is not assignable to type 'Promise<number>'.

27     const result = fn.call(instance);

I thought maybe it is because bluebird.each accepts either values or promise that resolve to values the compiler can't reconcile things, but the only solution I thought of there was to strongly type the return values"

async methodA: Promise<number> { /*...*/ }
methodB: number { /*...*/ }

But that didn't change anything. Also I note the following:

  • I have to provide context here, because invoking the functions in the each callbacks loses connection to the Template as this
  • When methodA is synchronous (remove the async keyword, remove the delay(), just return this.propertyA, this works fine.
  • When I remove the return statements things work fine.
  • When I change fn.call(instance) to fn.bind(instance)() it works fine

How can I satisfy the compiler so it knows how to call these functions with the provided context.

Is there an easier way to call these methods in sequence so their connection to this is maintained?

StackBlitz Example

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

It may help to look at the inferred types:

  • sequence: (((this: Template) => number) | ((this: Template) => Promise<number>))[] or just ((() => Promise<number>) | (() => number))[]
  • fn: ((this: Template) => number) | ((this: Template) => Promise<number>) or just (() => Promise<number>) | (() => number)
  • .call: <Template, [], number>(this: (this: Template) => number, thisArg: Template): number

and we can see that the type of the .call() expression is not what we expect - the compiler wants a function returning a number, and complains since fn can alternatively return a Promise<number>. This is probably due to a TypeScript bug when dealing with inferring the return type of function union types. It might be related to the subtle difference between X => A | B and (X => A) | (X => B).

We can fix this by writing

  • const result = fn.call<Template,[],number|Promise<number>>(instance); or
  • …(fn: () => number | Promise<number>)) => … or
  • const sequence: (() => number | Promise<number>)[]
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda