0

I'm having difficulty strongly typing my Twitter widget.

At the moment, it throws me a bunch of errors including:

ESLint: Unsafe call of an any typed value.(@typescript-eslint/no-unsafe-call)
ESLint: Unsafe member access .catch on an any value.(@typescript-eslint/no-unsafe-member-access)
ESLint: Unsafe member access .createTweet on an any value.(@typescript-eslint/no-unsafe-member-access)
ESLint: Unsafe member access .finally on an any value.(@typescript-eslint/no-unsafe-member-access)
ESLint: Unsafe member access .then on an any value.(@typescript-eslint/no-unsafe-member-access)

I'd like to fix this by creating an interface for the twi, but I'm unsure what that would look like.

  loadTwitterWidget(): void {
    this.setLoadingStatus.emit(true);
    this.courseContentElementEmbedTweetService
      .loadScript()
      .pipe(take(1))
      .subscribe(
        // I want to create an interface for this
        (twitter) => {
          (this.tweet.nativeElement as HTMLElement).innerHTML = null;
          // Errors occur here
          twitter['widgets']
            .createTweet(this.courseContentElementEmbed.id, this.tweet.nativeElement, {
              ...this.tweetOptions,
            })
            .then((r) => {
              if (!r) {
                this.setErrorStatus.next();
              } else {
                this.setSuccessStatus.next();
              }
            })
            .catch((error) => this.logger.error(error))
            .finally(() => this.setLoadingStatus.emit(false));
        },
        (error) => this.logger.error(error)
      );
  }

So far I've tried the following:

export interface ICourseContentElementEmbedTweetWidget {
  widgets: {
    createTweet: unknown
  }
  [key: string]: string;
}

But I get the error TS2411: Property 'widgets' of type '{ createTweet: unknown; }' is not assignable to string index type '.

Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
methuselah
  • 12,766
  • 47
  • 165
  • 315

2 Answers2

0

You can provide it as any like below or you can navigate to modules by pressing F12 if using vscode and search for createTweet you will get its data type there.

export interface ICourseContentElementEmbedTweetWidget {
  widgets: {
    createTweet: any
  }
  [key: string]: string;
}
Syed Mohib Uddin
  • 718
  • 7
  • 16
0

If you define properties on your type that are different from the type of the index signature, you will get an error message.

The reason is that you could access the widgets in two ways:

  • object.widgets OR
  • object["widgets"]

which are the same, but would have different types in your code.

To solve this, you can define the type of the index signature as a union type of the property types:

export interface ICourseContentElementEmbedTweetWidget {
  widgets: {
    createTweet: unknown
  }
  [key: string]: string | { createTweet: unknown };
}

This is described in the TypeScript docs here: https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures

However I would advise not doing this, because now you will have to check the type or do a type assertion whenever accessing the indexer. If you can, remove the indexer and specify only the properties that are available.

Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
  • Thanks. I tried this. But I now get the error `TS2349: This expression is not callable.   Type '{}' has no call signatures.` along with the `@typescript-eslint/no-unsafe-call` and `@typescript-eslint/no-unsafe-member-access` errors. Is there anyway around this? – methuselah May 06 '21 at 21:14
  • 1
    @methuselah I guess the error is shown when calling `createTweet`, right? If so, that is because unknown is not a function type. When accessing anyhting that is typed unknown you first have to check its type. But I would suggest changing the type from unknown to a function type with typed parameters. You can take a look here to check the parameter types: https://developer.twitter.com/en/docs/twitter-for-websites/embedded-tweets/guides/embedded-tweet-javascript-factory-function – Krisztián Balla May 07 '21 at 06:49
  • 1
    @methuselah are you using this Node module? https://www.npmjs.com/package/twitter-widgets – Krisztián Balla May 07 '21 at 06:54