#Can I return a non-Promise from a method that needs to wait on its Promise argument?

1 messages · Page 1 of 1 (latest)

crisp gullBOT
#
declare interface AssertionApi<E> {
  currentPromise: Promise<void>;
  actual: E;
  eql(expected: E): Promise<void>;
  ok(): Promise<void>;
  notOk(): Promise<void>;
}
declare class StringAssertions implements AssertionApi<string> {
  constructor(currentThis: Promise<void>, actual: string);
  currentPromise: Promise<void>;
  actual: string;
  eql(expected: string): Promise<void>;
  ok(): Promise<void>;
  notOk(): Promise<void>;
}

const foo = {
  expect<A>(this: Promise<void>, actual: A | Promise<A>): AssertionApi<A> {
    const handlePrimitive = (actual: A): AssertionApi<A> => {
      let assertionApi: AssertionApi<unknown>;
      switch (typeof actual) {
        case "string":
          assertionApi = new StringAssertions(this, actual);
          break;
        default:
          throw new Error(`Can't handle assertions on a ${typeof actual} type`);
      }
      return assertionApi as AssertionApi<A>;
    };
    if (actual instanceof Promise) {
      return this.then(() => actual).then((actualPrimitive) =>
//    ^^^^^^
// Type 'Promise<AssertionApi<A>>' is missing the following properties from type 'AssertionApi<A>': currentPromise, actual, eql, ok, notOk
        handlePrimitive(actualPrimitive),
      );
    } else {
      return handlePrimitive(actual);
    }
  },
};
fleet trench
#

In the context of this question, I want to assume that expect's actual is a Promise. I would like to be able to write the code as shown, but it returns a Promise<AssertionApi<A>> instead of a AssertionApi<A>

#

Is it possible to get the value of the promise within expect, or is that impossible unless I change the return type?

ionic badger
#

Hi there. First, never call your params this it's a reserved word. Second, if you want to await a promise inside the expect fn and then return the unwrapped value then the expect fn becomes async as well so it returns a promise itself. The only way to workaround is to use a callback that will be fired after a promise resolution.

#

Basically your expect function behaves synchronously when actual is a value and asynchronously when it's a promise. It's bad behavior as it's unpredictable. You need to change your api

cinder heath
#

Declaring a this function parameter is a TS feature, it allows you to type annotate what this should be.

ionic badger
cinder heath
#

Can't seem to find it in TS handbook.

crisp gullBOT
#
function greet(this: { name: string }) {
    console.log(this.name)
}

const foo = { name: 'foo', greet }
foo.greet()

const bar = { greet }
bar.greet()
//^
// The 'this' context of type '{ greet: (this: { name: string; }) => void; }' is not assignable to method's 'this' of type '{ name: string; }'.
//   Property 'name' is missing in type '{ greet: (this: { name: string; }) => void; }' but required in type '{ name: string; }'.