snoowrap icon indicating copy to clipboard operation
snoowrap copied to clipboard

Type error with async/await

Open Moebytes opened this issue 6 years ago • 12 comments
trafficstars

I updated to version 1.19.0 of the package (which includes typings). I get the following error when trying to await promises (Typescript):

Type is referenced directly or indirectly in the fulfillment callback of its own 'then' method

Here are the snippets that receive the error:

const user = await reddit.getUser(query.trim()).fetch() //param is string
const post = await reddit.getRandomSubmission()
const post = await reddit.getSubmission(postIDS[i]).fetch() //param is string
const posts = await reddit.getSubreddit(subreddit).getRandomSubmission() //param is string

This error seems to come from the package. While I don't see a mention of async/await in the docs, it did work perfectly before...

Moebytes avatar Oct 02 '19 22:10 Moebytes

Could you pinpoint where you're getting this? Or is this happening on all functions you mentioned?

Venefilyn avatar Oct 02 '19 22:10 Venefilyn

I've tried looking at some of the functions you mentioned but all type definitions are correct

Venefilyn avatar Oct 03 '19 08:10 Venefilyn

For reference, the entire file where I used snoowrap is here: https://github.com/Tenpi/Kisaragi/blob/master/commands/website/reddit.ts

I also found another issue from the DefinitelyTyped repo that reports the same: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/33139

I'm not entirely sure, but I think that the error has to do with promises that resolve to themselves. Using .then() syntax works perfectly, however. Don't worry too much about it though, I will just have typescript ignore the lines that give the error.

Moebytes avatar Oct 03 '19 21:10 Moebytes

That's unsettling.. does the error go away if you explicitly append .fetch()?

Venefilyn avatar Oct 04 '19 09:10 Venefilyn

I can confirm this issue. Code example is below, with the error message in the comments.

import Snoowrap from 'snoowrap';

async function main(): Promise<void> {
  const snoowrap = new Snoowrap(<login info>);
  const sub = snoowrap.getSubreddit('pics');
  /**
   * (method) RedditContent<Subreddit>.fetch(): Promise<Subreddit> 
   *
   * Type is referenced directly or indirectly in the fulfillment callback of
   * its own 'then' method.ts(1062)
   *
   */
  const subreddit = await sub.fetch();
  const newPosts = await subreddit.getNew();

  console.log(newPosts);
}

main();

garyking avatar Oct 27 '19 19:10 garyking

Anything new on this? PS thanks for a great package 👍

benjick avatar Apr 13 '20 13:04 benjick

Does anyone have an update on this? Even trying to work around it with fetch or then yields the same error.

prmichaelsen avatar Nov 04 '20 00:11 prmichaelsen

I'm also running into this issue. Is it really necessary for RedditContent to extend Promise? I feel it would be cleaner both from a typescript perspective and just for separation of concerns in general to have promised returns be explicit rather than implicit. Such a change would require a version bump, as it wouldn't be backwards compatible, but it would save my editor from constantly trying to correct comment.reply(...) to (await comment).reply(...).

bluecomm42 avatar Dec 02 '20 23:12 bluecomm42

Feel free to check out #296 . The issue is that the objects/RedditContent.d.ts declares

class RedditContent<T> extends Promise<T>

and it should just be

class RedditContent<T>

This works now without changing the underlying .js, this type declaration was just incorrect.

franklinharvey avatar Dec 22 '20 01:12 franklinharvey

Another hack/workaround for this is to use Omit<> type in TypeScript:

const unpromise = async <T>(promise: Promise<T>) => {
  const result = await promise;
  return result as Omit<T, 'then' | 'catch' | 'finally'>;
};

// This produces an error
const comment = await reddit.getComment('...');

// This does not produce an error
const comment = await unpromise(reddit.getComment('...'));

Tyrrrz avatar Mar 24 '22 22:03 Tyrrrz

A better quick fix is putting this in a ts file in your project. This way you don't need to cast or use a function. This then fixes it globally.

import * as snoowrap from "snoowrap";

declare module "snoowrap" {
  class RedditContent<T> {
    then: undefined;
    catch: undefined;
    finally: undefined;
  }
}

Loeffeldude avatar Jun 10 '22 21:06 Loeffeldude

A better quick fix is putting this in a ts file in your project. This way you don't need to cast or use a function. This then fixes it globally.

import * as snoowrap from "snoowrap";

declare module "snoowrap" {
  class RedditContent<T> {
    then: undefined;
    catch: undefined;
    finally: undefined;
  }
}

It doesn't set the return type to a promise so await will have a squiggly line

amosbastian avatar Aug 15 '22 16:08 amosbastian