Since ZK 9, we at ZK started to use TypeScript to create our new components. TypeScript is strong-typed and provides a better autocomplete feature in IDE. It reduces the possibility of running into common JavaScript mistakes. In this blog post, we’ll share with you how you can write your own ZK component in TypeScript.

Create a Component Project

You can create your own ZK component, and use it in your ZK web app projects. Instead of creating the component from scratch, it’s easier to use a boilerplate project, so we have published a zk-archetype-component for Maven.

For a detailed how-to tutorial, please refer to Creating ZK Component with Maven Archetype and follow the steps in the document to create a ZK component project.

Now that you have the (js) component project, we’ll need to introduce TypeScript into the project.

Convert the .js into .ts

To enable TypeScript, we use Babel to compile .ts files to .js. Also, we need to install Node.js (and npm).

Follow these steps to convert the JS into TS:

  1. Rename your widget JS file (e.g. MyComponent.js → MyComponent.ts), but keep the mold JS unchanged.
  2. Add these necessary configuration files to the root folder.
    • package.json (For npm dependencies)
    • .babelrc (For Babel)
    • gulpfile.js (For Gulp, a build system)
    • tsconfig.json (For TypeScript)
  3. Run npm install (Node.js is needed)
  4. To compile ts files run npm run build.
  5. To automate the process, you can include the frontend-maven-plugin in pom.xml to download Node.js binaries, install dependencies, and execute the NPM jobs in the Maven build cycle. See the example project for detail.
Add these necessary configuration files to the root folder

Autocomplete in IDE

Autocomplete feature in IDE

A killer feature of TypeScript is the type declarations (@types). By including these types the IDE can perform autocomplete fluently. You no longer have to look up external documents for API usages or check how many parameters are needed. The IDE will do these for you and it boosts the development efficiency a lot.

Add types to method return and parameters

There are many predefined basic types in TypeScript:

  • string: A string type.
  • number: Any number including integer and decimal.
  • boolean: A Boolean type (true or false).
  • void: No return.
  • any: A special type that means anything, just like the var in JavaScript. Avoid using it unless you have to since it will disable type-checking.
  • Array<T>: An array representation of T. Or can be written as T[].

And some interfaces in DOM:

  • Element: An element from a Document (might be a HTMLElement or a SVGElement).
  • Window: The window object.
  • Document: The document object.

Since JavaScript doesn’t have any hint for types of methods or variables, adding them in TypeScript can help us with autocompletion and type checking. We can add these types in every method to ensure TS has the information. Next time we call this.myMethod(), TS knows the exact type, and the autocomplete feature in IDE can be useful after typing dot (.).

The following snippet is taken from the example project, adding the return types so we know this._newDataSource() returns a Datasource, and the param is an instance of IGetRowsParams, which has properties of startRow, endRow, sortModel, filterModel, successCallback, and failCallback.

_newDataSource(): IDatasource {
	let self = this;
	return new class implements IDatasource {
		getRows(params: IGetRowsParams): void {
			let {startRow, endRow, sortModel, filterModel, successCallback, failCallback} = params;
			try {
				self.fire('onPaging', {startRow, endRow, sortModel, filterModel});
				self._successCallback = successCallback;
			} catch (e) {
				failCallback();
			}
		}
	};
},

Additional Benefit: supports ES6+ new features

Before ZK9, we couldn’t use new features introduced in ECMAScript 6 because Internet Explorer 9 didn’t support them. Now, after using TypeScript, all TS code will be compiled into ES5-compatible JS, which means we can use these new features regardless whether the browser supports it or not:

  • Arrow function: (a, b) => a + b;
  • Function declaration in object: myMethod() {}
  • Use let/const definition: let a = 1;
  • Destructive assignment: var {a, b} = obj;
  • Template literals: `hello ${name}`
  • Object rest spread: var myOptions = {...options, force: true};
  • Use async/await:
    async function myFetch(url) { var res = await fetch(url); ... }

Advanced Feature: live reload during development

TypeScript has to be compiled into JavaScript before it runs in the browser. We can do this by executing npm run build on file changes, but during development we can use live reload to help with the routine job.

In the example project, we added a command (npm run dev) in package.json. After executing it:

  • BrowserSync creates a dev proxy to port 8080.
  • Gulp will watch for any TypeScript file changes.
  • Babel will be invoked to compile them automatically.
  • BrowserSync will be notified to refresh the browser.

Instead of localhost:8080, localhost:3000 will refresh the browser automatically while the resources are updated. It not only does the job for you but also saves time for recompiling the whole project when you changed just a single file.

Summary

After using TypeScript, static type-checking reduces human mistakes, and the autocomplete feature makes coding easier. In addition you can now use new features in the latest ECMAScript versions regardless of the browser support.

Demo Project

The project contains a custom ZK-aggrid component for demonstrating how you can create a custom component using Typescript. The source code of the demo project and the included ag-Grid Community library are both licensed under the MIT License.

GitHub repo: zkoss-demo/zk-aggrid-component-example

Remember that the project is for demonstrating purpose only, it is not an official ZK component and not meant to be used in production environments.

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.

Leave a Reply