Skip to main content

Typesafety

One of the most exciting features of genezio is the guaranteed type safety between backend services and clients, made possible by the autogenerated SDK, which is able to construct types matching the server side types used for the RPC calls exposed to the clients. This feature is designed to be language agnostic, and with time, genezio will develop support for more and more languages.

Right now, Genezio has support for a variety of programming languages on the server side:

  • TypeScript
  • JavaScript

And can export a typesafe SDK in any of the following languages:

  • TypeScript
  • JavaScript
  • Go
  • Dart
  • Kotlin
  • Python
  • Swift

Genezio Classes

To be able to generate and ensure a server-client communication, Genezio requires the use of classes. These classes are decorated with the @GenezioDeploy decorator, which tells genezio to generate an SDK for the class.

The following snippet of code shows a simple HelloWorldService class:

service.ts
import { GenezioDeploy } from "@genezio/types";

@GenezioDeploy()
export class HelloWorldService {
hello(name: string, sender: string): string {
console.log(`Hello world request received with name ${name} from ${sender}!`);

return `Hello, ${name}, from ${sender}!`;
}
}

Genezio methods

There are 2 very simple rules for defining type-safe RPC calls in genezio.

  • each parameter of a method must be serializable
  • the return type of a method must be serializable

Serializable types

In this section we will take a look at serializable types supported by genezio and their implementation in different languages.

Here is a summary of serializable genezio types:

TSGoDartKotlin
Primitives
Objects
Arrays
Maps
Enums
Unions
Any
Interfaces

Primitive types

  • number
  • string
  • boolean

Objects

An object is serializable if all of its fields are serializable.

There are many ways of declaring objects in TypeScript. Genezio prefers type aliases instead of interfaces or classes.

type Person = {
name: string;
age: number;
};

Arrays

An array of a type T is serializable if T is serializable

type User = {
name: string;
age: number;
};

@GenezioDeploy()
export class UserService {
getNames(users: User[]): string[] {
return users.map((p) => p.name);
}
}

Maps

A map with keys of type string and values of type T is serializable is T is serializable

type User = {
name: string;
age: number;
};

@GenezioDeploy()
export class UserService {
getUserForKey(users: { [key: string]: User }, key: string): User {
return users[key];
}
}

Enums

Enums representing consecutive numbers starting from 0 are serializable

export enum Season {
WINTER,
SPRING,
SUMMER,
AUTUMN,
}

@GenezioDeploy()
export class UserService {
getSeasonTemperature(season: Season): number {
switch (season) {
case Season.WINTER:
return 0;
case Season.SPRING:
return 15;
case Season.SUMMER:
return 30;
case Season.AUTUMN:
return 10;
}
}
}

Unions

A union in typescript is serializable if all of its types are serializable

type City = {
name: string;
population: number;
};

type Country = {
name: string;
language: string;
};

@GenezioDeploy()
export class UserService {
getName(a: City | Country): string {
return a.name;
}
}

"Any" values

There are a few instances when genezio cannot construct a client type for the SDK, or the server type is explicitly defined as an "any" type. Genezio will use the most generic type available in the target language.

any