One of the core reasons why users love to work with ZK is the ability to interact with the Web frontend with Java alone. No messy HMTL, CSS, nor JavaScript; just good-old Java. However, there are still occasions where you want to get your hands dirty with JavaScript, e.g., creating custom components. As a dynamically-typed language with lots of quirks (1 == [“001”] is true?!), using JavaScript is like programming blind, and Java developers may often feel discouraged when customizing the frontend.

Well, not anymore. With the zk-types NPM package, you can now use TypeScript to customize the ZK 10 frontend with an experience similar to programming in Java.

Benefits of TypeScript

TypeScript is a statically-typed language that compiles to JavaScript. TypeScript syntax is based on JavaScript but comes closer to Java syntax. Being statically typed, TypeScript provides the following benefits that Java developers enjoy but were out of reach with pure JavaScript.

  1. Reliable auto-completion; one doesn’t have to wade through API references on the Web.
  2. Easy code navigation by clicking on names instead of searching the whole codebase.
  3. Eliminate typos (e.g., misspelling isAlign as isalign) and mismatching types (passing a string when a number is expected).
  4. Safe inter-op between various module systems (ESM, CommonJS, SystemJS AMD, and global UMD). One can even import a JSON file directly as a type-safe object.
  5. Enable type-aware lint rules. This allows us to craft custom ESLint rules to enforce project wide conventions which can also be automatically fixed by the linter.
  6. Automatic link validation and name/type matching in JSDoc, ensuring stronger synchronization between the documentation and the actual code.

These are the vast improvements we experienced first-hand on a daily basis while working with TypeScript. All in all, TypeScript enables an enormous amount of automated validations and automatic corrections that make ZK 10 easy and safer to use.

zk-types is Optional and Backward-compatible

ZK-types is a new way to customize the ZK 10 frontend that brings smart IDE feedbacks and a more Java-like programming experience.

[Since ZK 10]

If you have been customizing the ZK frontend with JavaScript, those customizations will continue to work. The purpose of zk-types is merely to boost developer experience with TypeScript. Also, zk-types completely covers all existing ZK frontend API without breaking existing behavior.

ZK10 + TypeScript with zk-types

Having reaped the benefits of a statically-typed ZK framework, we would like to share the gospel with you so that you can enjoy the same benefits when customizing the frontend. See the demo at zk-types-demo. The setup is minimal, but you can also just clone the demo:

  1. Open a new project.
  2. Get the types with: npm install zk-types
  3. Install TypeScript with: npm install typescript
  4. Create the template TypeScript configuration: npx tsc --init
  5. Modify tsconfig.json to have "types":["zk-types"]
  6. Create a .ts file and start programming. Start typing zk., and you should see the IDE showing auto-complete hints; IDE support is detailed in the box below.
  7. Compile the .ts file with npx tsc (do not specify the filename). You should see an emitted .js file. Copy the .js file to wherever appropriate.

Note that the zk-types NPM package is very lean (under 1 MB); it contains only the type definitions (.d.ts files) for the ZK framework. This is another benefit that TypeScript brings: the possibility to code against type definitions then link with existing JavaScript in deployment, much like how C programmers code against a few header files then link with existing binaries on whatever machine they are targeting.

Visual Studio Code and IntelliJ IDEA Ultimate are known to support TypeScript out-of-the-box. IntelliJ IDEA Community does not; please read the this announcement. You will have the best experience when using the supported IDEs.

Exemplary Features of zk-types

From our experience with other JavaScript libraries that also migrated to TypeScript, we noticed how the quality of type annotation affects developer experience. Thus, when preparing ZK 10, we went to lengths to remodel the whole JavaScript codebase with TypeScript appropriately:

  1. Prefer ES6+ syntax, as transpilation, down-leveling, and polyfills will be automatically done.
  2. Replace ad-hoc conventions with first-class language features. The most significant being the deprecation of the zk.$extends pattern in favor of ES6 classes.
  3. Provide a painless deprecation story. Despite replacing zk.$extends with ES6 classes throughout the codebase, we made sure that zk.$extends (1) works as it previously did, (2) can successfully inherit from ES6 classes, (3) allows ES6 classes to successfully inherit from it, and (4) type-annotated in detail.
  4. Aim for null-safety. We made infrequent and consistent the use of null, undefined, uninitialized variables, and optional parameters.
  5. Use generics to model the DOM element type of zk.Widget and the value type of zul.inp.InputWidget.
  6. Narrow down the specification of types. E.g., specify HTMLDivElement instead of the wider HTMLElement, and prefer concrete types to any or unknown.
  7. Incorrect type annotation is the most damaging of all. Since it is easy to introduce typos and other defects during the migration from JavaScript to TypeScript, a large part of the migration is automated.

Take, for instance, zk.augment, the type-safe successor of zk.override. The return value of zk.augment backs up the overridden properties of its first argument, and the return types are designed to automatically narrow down to only those overridden properties. In the illustration below, the overridden properties are the methods _init and hasNext. In fact, the method signatures are also auto-inferred as shown in the auto-complete popup: hasNext(): boolean. How convenient!

Type-safe zk.augment with hints.

The overall zk-types experience is immediate, reliable, accurate, and delightful. We invite you to try out this new approach and let us know what you think!

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