ak1394 / react-native-tts

React Native Text-To-Speech library for Android and iOS
601 stars 154 forks source link

Cannot read property 'speak of undefined' #124

Open HarryShotta opened 4 years ago

HarryShotta commented 4 years ago

I am trying to run the function: Tts.speak('Hello, world!', { iosVoiceId: 'com.apple.ttsbundle.Moira-compact' }); I get the following error: Cannot read property 'speak of undefined'.

I don't know if either of these things are to do with the speak error, but I thought I would mention them just in case they are helpful.

I also had an error when trying to: import Tts from 'react-native-tts';

(Could not find a declaration file for module 'react-native-tts'. 'c:/Users/charl/Desktop/randomProject/node_modules/react-native-tts/index.js' implicitly has an 'any' type. Try npm install @types/react-native-tts if it exists or add a new declaration (.d.ts) file containing `declare module 'react-native-tts')

After having created a .d.ts file, this error disappears, but the speak error still persists. Also, when poking around in the node_modules, the react-native-tts package.json file has a warning on "bundleDependencies": false, .

Any help with this would be appreciated.

alexfinnarn commented 4 years ago

Could it be https://github.com/ak1394/react-native-tts#waiting-for-initialization?

The declaration file is specifically for TypeScript, and I don't think that warning is a problem. It just means that TS can't infer the type and statically analyze your code...I don't use TS much though, so...

I hope this module works well for me, but I have used Expo's Speech module as an alternative although this looks more fully-featured.

sseppola commented 4 years ago

Your first problem was that TS couldn't find a TS definition for the module, after creating one the problem was that it was empty, so it would warn you that that what you imported is undefined because your definition file is empty.

Here's a rough TypeScript definition I threw up to use this module:

declare module 'react-native-tts' {
  type SupportedEventsT =
    | 'tts-start'
    | 'tts-finish'
    | 'tts-pause'
    | 'tts-resume'
    | 'tts-progress'
    | 'tts-cancel';

  export class ReactNativeTTS {
    /**
     * getInitStatus
     * Android only, stubbed for iOS
     */
    getInitStatus: () => Promise<boolean>;

    /**
     * requestInstallEngine
     * Android only, stubbed for iOS
     */
    requestInstallEngine: () => Promise<boolean>;

    /**
     * requestInstallData
     * Android only, stubbed for iOS
     */
    requestInstallData: () => Promise<boolean>;

    /**
     * setDucking
     */
    setDucking: (enabled: boolean) => Promise<'success'>;
    // setDucking(enabled) {
    //   return TextToSpeech.setDucking(enabled);
    // }

    /**
     * setDefaultEngine
     * Android only, stubbed for iOS
     */
    setDefaultEngine: (engineName: string) => Promise<boolean>;

    /**
     * setDefaultVoice
     */
    setDefaultVoice: (
      voiceId: string,
    ) => Promise<
      'success' | 'lang_country_available' | 'lang_country_var_available'
    >;

    /**
     * setDefaultRate
     */
    setDefaultRate: (rate: number, skipTransform: boolean) => Promise<null>;

    /**
     * setDefaultPitch
     */
    setDefaultPitch: (pitch: number) => Promise<null>;

    /**
     * setDefaultLanguage
     */
    setDefaultLanguage: (
      language: string,
    ) => Promise<
      'success' | 'lang_country_available' | 'lang_country_var_available'
    >;

    /**
     * setIgnoreSilentSwitch
     * iOS only, stubbed for Android
     */
    setIgnoreSilentSwitch: (
      ignoreSilentSwitch: 'ignore' | 'obey',
    ) => Promise<'success'>;

    /**
     * voices
     */
    voices: () => Promise<
      Array<{
        id: string;
        name: string; // ios only
        language: string;
        quality: number;
      }>
    >;

    /**
     * engines
     * Android only, stubbed for iOS
     */
    engines: () => Promise<
      Array<{
        name: string;
        label: string;
        default: boolean;
        icon: number;
      }>
    >;

    /**
     * speak
     */
    speak: (
      utterance: string,
      options?: Partial<{
        rate: number;
        voiceId: string;
        androidParams: Partial<{
          KEY_PARAM_PAN: string;
          KEY_PARAM_VOLUME: string;
          KEY_PARAM_STREAM: string;
        }>;
      }>,
    ) => Promise<string>;

    /**
     * resume
     */
    stop: (onWordBoundary?: boolean) => Promise<boolean>;

    /**
     * pause
     * iOS only, stubbed for Android
     */
    pause: (onWordBoundary?: boolean) => Promise<boolean>;

    /**
     * resume
     * iOS only, stubbed for Android
     */
    resume: () => Promise<boolean>;

    addEventListener: (type: SupportedEventsT, handler: () => void) => void;

    removeEventListener: (type: SupportedEventsT, handler: () => void) => void;
  }

  const tts: ReactNativeTTS;
  export default tts;
}

I haven't used the whole api, so there may be issues with these types, but this should solve your problem.

htbkoo commented 3 years ago

@sseppola

Thanks a lot for the TypeScript definition! It is very helpful when I was trying to use this library in my TypeScript project (though it would be the best if there is actually a @types package for the types definitions published on npm 😅 )

Just a minor thing regarding the types definitions: For the speak function, maybe we would need a different types for the androidParams, i.e.

    /**
     * speak
     */
    speak: (
      utterance: string,
      options?: Partial<{
        rate: number;
        voiceId: string;
        androidParams: Partial<{
          KEY_PARAM_PAN: number;
          KEY_PARAM_VOLUME: number;
          KEY_PARAM_STREAM:
            | "STREAM_ALARM"
            | "STREAM_DTMF"
            | "STREAM_MUSIC"
            | "STREAM_NOTIFICATION"
            | "STREAM_RING"
            | "STREAM_SYSTEM"
            | "STREAM_VOICE_CALL";
        }>;
      }>,
    ) => Promise<string>;

This is because, according to the documentation, I think both KEY_PARAM_PAN and KEY_PARAM_VOLUME seem to be a number type and it seems KEY_PARAM_STREAM would be one of STREAM_ALARM, STREAM_DTMF, STREAM_MUSIC, STREAM_NOTIFICATION, STREAM_RING, STREAM_SYSTEM, STREAM_VOICE_CALL. <- Please correct me if I am wrong, @ak1394

Anyway, thanks again for posting the type definitions! :+1: