webapp-schulverwaltung

back

Data Decoding with io-ts

Introduction

Since the backend of this application is developed and operated by a third party, we use io-ts to ensure the received data from the API conforms to the expectations. The mechanism works as follows:

Best Practices

Type Definition

Runtime types are described in a .model.ts file in the src/app/shared/models directory:

import * as t from 'io-ts';

const Person = t.type({
  Id: t.number,
  FirstName: t.string,
  LastName: t.string
});

type Person = t.TypeOf<typeof Person>;
export { Person };

The runtime and TypeScript types are exported under the same name and can be used in their appropriate contexts without having to think about which one to use.

Avoid Checking Unused Properties

Any additional properties that are received but are not used within the application (e.g. a MatriculationNumber on Person), should be omitted from the type definition. These properties then stay in the decoded object, but are ignored when type checking. The goal is to not generate unnecessary exceptions.

Decoding

The decode and decodeArray utility functions can be used to type-check and decode the received data:

function getPerson(id: number): Observable<Person> {
  return this.http
    .get<unknown>(`/api/Persons/${id}`)
    .pipe(switchMap(decode(Person)))
    .subscribe(...);
}