Using TypeScript with the Twilio Flex Agent UI Sample - Perficient Blogs
Blog
  • Topics
  • Industries
  • Partners

Explore

Topics

Industries

Partners

Using TypeScript with the Twilio Flex Agent UI Sample

When we first started working with the Flex samples provided by Twilio, the source code was provided in TypeScript. This provided a dev-time programming environment that I tend to prefer, even though I am far from a TypeScript expert. As Flex and the quick-start samples moved toward general availability, Twilio made the choice to switch to using the popular create-react-app package with “plain javascript”. This decision is understandable as not everyone has TypeScript expertise or wants to use TypeScript in their front-end development pipeline.

After Flex v. 1.0 was released at Signal, the sample projects for both the agent console (flex-ui-sample) and web chat (flex-webchat-ui-sample) are now provided at GitHub. In addition. the new flex-plugin-builder sample is available there as well. This allows developers to consume the latest Flex sample code just like any other NPM package.

Decision Considerations

We’ve had a number of internal debates over whether to standardize on TypeScript internally for our Flex projects or stay close to the samples. Twilio is still using TypeScript for most internal projects and it is still a highly recommended approach. The number of beneficial things you get with TypeScript is no secret, including interface definition, better typing of variables and objects and additional hooks for IDEs for intellisence and other syntactic sugar. A developer also typically catches a lot more errors at compile-time vs. run-time.

That being said, standardizing on TypeScript means you need to keep track of changes to the default sample yourself. You are responsible to keep those changes synced up with your TypeScript version. This may not make sense for simple projects. However, we expect longer term projects to eventually have a large and unique code-base. This probably means that the sample projects are used more for reference anyway.

flex-ui-sample: The TypeScript version

I decided to go through the exercise of getting the flex-ui-sample running in TypeScript. It certainly was not as straight-forward as I was expecting. Ultimately it wasn’t incredibly difficult, but you certainly need to have a bit of familiarity with TypeScript, including how typings files work. See the much longer read here.

To keep things rather boilerplate, I went down the path of generating a new project using create-react-app with the TypeScript support flag. The Twilio node module was then added to package.json. I then manually merged and updated the standard files to closely mimic the GitHub standard JavaScript version. I guess you could also try to get TypeScript working in an original flex-ui-sample clone, but this seemed error prone and trickier to manage to me.

Basic Steps

(As I mentioned I would not consider myself an expert on this yet, so happy to take any comments or suggestions for better ways to do the following.)

  • If you don’t already have a default repo of flex-ui-sample from GitHub, grab that first so you have something to compare to.

  • Create a new directory for your repo.

  • if you don’t already have the create-react-app package installed, install it (npm install -g create-react-app).

  • In your new directory, run create-react-app your-app-name –scripts-version=react-scripts-ts

  • Add the current Twilio UI reference to your package.json. I used the latest version as of the writing of this post. (“@twilio/flex-ui”: “^1.1.0”). Run npm install again to pull in the dependencies.

  • I used Beyond Compare for some of this work. Use whatever compare/diff tool you like or you can also just put the two projects side by side. I’m not going to go through all the changes line by line, but this should get you close.

    • Update the public\index.html to match the flex-ui-sample default. You can just copy over the file contents if you wish.

    • Create an assets directory in public and copy a valid appConfig.js from a working project (or create a new one).

    • The default registerServiceWorker.ts file should be fine.

    • You’ll need some @types files.

      • npm install @types/react-router

      • npm install @types/react-router-redux

      • The types file for twilio-taskrouter isn’t set up properly for the compiler to find it. Go here to get it. It won’t work as-is, you will need to make some changes. Save this file (index.d.ts) in a new path you set up – node_modules\@types\twilio-taskrouter

        • in the Worker class, add the : void as the return type for the disconnect and updateToken methods.

        • in the Task class, get rid of the curly braces around the reason parameter in the wrapUp method.

        • in the Reservation class, add : Promise<Reservation> as the return type for the redirect method.

  • At this point if you compile you are going to get some additional complaints. You can try to solve them or you can just go into tsconfig.json and add “skipLibCheck”: true to the compilerOptions object.
  • Similarly, you can either resolve all the default tslint options or take the lazy way out like I did. During development, I like to use a lot of console logging so I set the “no-console” rule to false. I also set “ordered-imports” and “jsx-no-lambda” to false. All depends on how strict you want your project to be. You can always get more strict later.

Flex Project Specifics

  • Replace the “body” style in index.css with the “body, #root” style from the default sample.

  • For index.tsx, you basically want to make it look like the index.js from the default sample. However, you’ll need to update it for TypeScript.

      • Imports section

        import * as React from 'react';
        import * as ReactDOM from 'react-dom';
        import * as Flex from "@twilio/flex-ui"
        import './index.css';
        import registerServiceWorker from './registerServiceWorker';

    • const mountNode – you need : HTMLElement as the type and you’ll need to add an exclamation point (non-null assertion marker) after the document.getElementById(“root”) call. This basically tells tslint “i’m making sure you’ll find a root element”.

       const mountNode: HTMLElement = document.getElementById("root")!;

    • const predefinedConfig – a couple of ways to do this, but I used (window as any).appConfig to get the TypeScript compiler to be happy

    • in renderApp, set the manager type to Flex.Manager

    • Replace <App manager={manager} /> with <Flex.ContextProvider manager={manager} > <Flex.RootContainer /> </Flex.ContextProvider>

      function renderApp(manager: Flex.Manager) {
      ReactDOM.render(
      <Flex.ContextProvider manager={manager} >
      <Flex.RootContainer />
      </Flex.ContextProvider>,
      mountNode
      );
      }

    • in handleError, set the parameter “error” type to : any

    • I wrapped the ReactDOM.render call in a /* tslint: disable */ just to not fight the “lambda in render” complaint. If you want to be strict about this, you can re-factor accordingly.

      /* tslint: diable */
      ReactDOM.render(
      {
      setRuntimeConfig(loginData, runtimeDomain);
      window.location.reload();
      }}
      />,
      mountNode
      );
      /* tslint: enable */

    • in setRuntimeConfig, I set the two parameters types to : any. You can of course be more strict if you wish.

Conclusion

At this point, you should be close enough to get the app to compile. Run npm start to get the default agent console available in your local browser. Keep in mind the default TypeScript port is 3000, not 8080 as in the typical sample. There may be additional work here if you want to get other elements working, such as the Actions or Notifications framework. I haven’t tried this yet, although those two examples worked fine in older samples built in TypeScript. And it’s possible there will be additional issues with typing files or other packages in a more fully implemented project. So consider this more of a proof of concept. As we continue to build out Flex implementations on my team, I’m sure we will continue to discuss when TypeScript makes sense when starting a project.

Have you tried using TypeScript since Flex went GA? Curious to hear your experiences. Also curious to hear your reasons for sticking to plain JavaScript and why that might be a better fit for you.

Leave a Reply

Subscribe to the Weekly Blog Digest:

Sign Up