Skip to content

Strong Typing

From the AppRun architecture and AppRun event life cycle, we can see two places that require strong typing: state and event names.

  • The initial state and the state passed between the view function and event handlers
  • The event names for publishing and subscribing to Apprun events

Strong Typing of State

The state is used in the view function and in the update(event handlers). We can make the state strong typed in the view function and in the update.

Typed View

First, we can make the state used in the view strongly typed by importing the View type from AppRun and applying it to the view function.

import { app, View } from 'apprun';
const view: View<number> => state => <div>...</div>

The View type imported from AppRun is a generic type. It makes the view function into a generic function, which let us define the type of its parameters. E.g., we define the view function to be View, TypeScript recognizes the state parameter of the view function is a number. typed view

Typed Update

Next, let's import the Update type from AppRun and apply it to the update object.

import { app, View, Update } from 'apprun';
const update: Update<number> = { ... }

The Update type imported from AppRun is also generic. It makes the event handlers in the update object into generic functions. TypeScript recognizes the state parameter of the event handler functions as are number.

Typed Update

Typed Application

Finally, let's make the application strongly typed. The app.start is a generic function already. If we give the app.start function a type, E.g., number, it means the state of the application is number, the view of the application is View and the update of the application is Update.

app.start<number>( ... )

If the type of state does not match the types assigned to the app.start function, TypeScript catches the type error.

Catch State Type Error

If the type of the view function does not match the types assigned to the app.start function, TypeScript catches the type error.

Catch View Type Error

If the type of the update object does not match the type assigned to the app.start function, TypeScript catches the type error.

Catch Update Type Error

So far, e have made the strongly typed state to the view function, the event handlers in the update object, and the application. Next, we will move to make strongly typed events.

Strong Typing of Events

AppRun update object is a named collection or dictionary of the event handlers. The event names are strings, such as +1 and -1. They are not typed, not checked by the compiler, and not IDE friendly. Instead, we can use the TypeScript enum to define the event names.

Enum of Event Names

We define the Events enum and use it in the view functions and the update object.

enum Events { inc = '+1', dec = '-1' }

Enum of Event Names

You can see when we type 'Events.', Visual Studio code provides the intelliSense to help us typing. However, you can also see that the string +0 is still allowed in the update object. It is because the object index can only be a number or string. Or as long as a number or string is used, the compiler is happy and has no more type checking.

Update Tuple

The update can be an array of tuples for defining AppRun event handlers.

Update Tuple

The event handler tuple has two fields: the event name and the event handler function.

We can use two advanced TypeScript types the tuple: union type and string literal type, to create so call discriminated union. For more information about union type, string literal type, and discriminated union, please refer to the TypeScript handbook.

Discriminated Union Typed Event Names

First, we define a union type called Events, which is made out of two string literal types, -1 and +1.

type Events = '-1' | '+1';

Then, we use the Events type as the second generic of the Update type imported from AppRun and apply it to the update tuple.

const update: Update<number, Events> = [ ... ]

The event names are strongly typed. TypeScript can even provide code auto-completion (IntelliSense) to hint at the event names.

Typed Update Tuple

If the event name is not one of the strings defined in the Events type, TypeScript catches the error.

Catch Event Name Error in Update Tuple

Typed Events in View

To make the event names in the view function strongly type, we need to make the event names of the application strongly type first. We can add the Events type to the app.start_ the generic function.

app.start<number, Events>(...)

It makes the application only can trigger the events that are defined in the Events type. Because we have made the event names strongly typed TypeScript provides intelliSense to the event names of the application.

Typed Event Names in the Application

TypeScript also catches the event name errors in the view function.

Catch Event Name Error in View

So far, we have accomplished strong typing for the AppRun global application. Next, we will implement strong typing for AppRun Components.

Strong Typing of Component

AppRun Component is like a scoped AppRun application. It also has three parts: state, view, and update.

AppRun Component is a generic class. We create our components by extending the AppRun Component class. We can add the state type and events type to the Component class, as well as to the view function, and update the tuple to make the component strongly typed so that TypeScript can provide IntelliSense and type validation while we are coding.

Typed State and Type Event Names in Component

Typed Event Decorator

The AppRun @on decorator makes a function in the component class to be an event handler. The @on decorator is also generic. When we add the event type to the @on the decorator, TypeScript recognizes and enforces the event names to be the event type.

Typed On Decorator

Typed $on Directive

The AppRun directive is a syntax sugar for JSX. The $on directive is helpful for publishing DOM events to AppRun events. The $on directive can be strongly typed.

Typed $on Directive

Conclusion

Thanks to TypeScript, we can make AppRun application strong-typed.