user1037355
user1037355

Reputation:

How to import types into vue2 typescript project

This repo is the types for the youtube api

https://www.npmjs.com/package/@types/youtube

What is the proper way to import these types into a vue2 project?

The following code complains as the type is not defined. But if i import the type ts complains and says missing dependency.

<template>
  <div ref="ytplayer" class="MYouTube"></div>
</template>

<style lang="scss" scoped>
.MYouTube {
  position: relative;
  margin: 0 auto;
  padding-bottom: 56.25%;

  .iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
  }
}
</style>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import getYoutubeId from '@/utils/getYoutubeId';
import reframe from '@/utils/reframe';
import injectScript from '@/utils/injectScript';

@Component
export default class MYouTube extends Vue {
  @Prop({ required: true })
  url!: string;

  vidId = '';
  $refs!: {
    ytplayer: any
  };

  created () {
    const vidId = getYoutubeId(this.url);
    if (vidId) {
      this.vidId = vidId;
    }
    injectScript('https://www.youtube.com/iframe_api', () => {
      this.injectAndPlay();
    });
  }

  injectAndPlay () {
    new YT.Player(this.$refs.ytplayer, {
      videoId: this.vidId,
      playerVars: {
        'playsinline': 1
      },
      events: {
        'onReady': (event) => {
          event.target.playVideo();
          reframe(this.$refs.ytplayer);
        },
        'onStateChange': () => {
          console.log('do something');
        }
      }
    });
  }
}
</script>

I have a global.d.ts but in here I can only declare YT as any:

interface Window {
  YT: any
}

In the tsconfig:

    "typeRoots": [
      "node_modules/@types"
    ],

but this does not auto resolve :/

Upvotes: 0

Views: 463

Answers (1)

tony19
tony19

Reputation: 138226

Types

No need to add a typeRoots in tsconfig.json for this.

Import the types in the type declarations file as yt, and replace YT: any with YT: yt:

// global.d.ts
import yt from '@types/youtube'

// `yt` needs to be outside of `global` for some reason
interface Window {
  YT: yt;
}

declare global {
  interface Window {
    onYouTubeIframeAPIReady?: () => void;
  }
}

If using VS Code, make sure to restart the IDE so that the file is properly indexed.

ESLint

Configure the YT global (and restart your dev server if running):

// .eslintrc.js
module.exports = {
  globals: {
    YT: true,
  },
}

Example usage

<template>
  <div>
    <div ref="ytplayer"></div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class extends Vue {
  vidId = 'M7lc1UVf-VE'

  mounted(): void {
    window.onYouTubeIframeAPIReady = () => {
      new YT.Player(this.$refs.ytplayer as HTMLElement, {
        videoId: this.vidId,
        playerVars: {
          playsinline: 1
        },
        events: {
          onReady(event: YT.PlayerEvent) {
            event.target?.playVideo()
          },
          onStateChange() {
            console.log('do something')
          }
        }
      })

      delete window.onYouTubeIframeAPIReady
    }

    const script = document.createElement('script')
    script.src = 'https://www.youtube.com/iframe_api'
    const firstScriptTag = document.getElementsByTagName('script')[0]
    firstScriptTag.parentNode?.insertBefore(script, firstScriptTag)
  }
}
</script>

GitHub demo

Upvotes: 1

Related Questions