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:
- TypeScript
- JavaScript
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}!`;
}
}
import { GenezioDeploy } from "@genezio/types";
@GenezioDeploy()
export class HelloWorldService {
hello(name, sender) {
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:
TS | Go | Dart | Kotlin | |
---|---|---|---|---|
Primitives | ✅ | ✅ | ✅ | ✅ |
Objects | ✅ | ✅ | ✅ | ✅ |
Arrays | ✅ | ✅ | ✅ | ✅ |
Maps | ✅ | ✅ | ❌ | ✅ |
Enums | ✅ | ❌ | ❌ | ✅ |
Unions | ✅ | ❌ | ❌ | ❌ |
Any | ✅ | ✅ | ✅ | ✅ |
Interfaces | ❌ | ❌ | ❌ | ❌ |
Primitive types
- TypeScript
- Go
- number
- string
- boolean
- int
- float64
- string
- bool
Objects
An object is serializable if all of its fields are serializable.
- TypeScript
- Go
There are many ways of declaring objects in TypeScript. Genezio prefers type aliases instead of interfaces or classes.
type Person = {
name: string;
age: number;
};
type Person struct {
Name string
Age number
}
Arrays
An array of a type T is serializable if T is serializable
- TypeScript
- Go
type User = {
name: string;
age: number;
};
@GenezioDeploy()
export class UserService {
getNames(users: User[]): string[] {
return users.map((p) => p.name);
}
}
type User struct {
Name string
Age number
}
type UserService struct {}
func New() UserService {
return UserService{}
}
func (s *UserService) GetNames(users []User) ([]string, error) {
var names []string
for _, user := range users {
names = append(names, user.Name)
}
return names, nil
}
Maps
A map with keys of type string
and values of type T is serializable is T is serializable
- TypeScript
- Go
type User = {
name: string;
age: number;
};
@GenezioDeploy()
export class UserService {
getUserForKey(users: { [key: string]: User }, key: string): User {
return users[key];
}
}
type User struct {
Name string
Age int
}
type UserService struct {}
func New() UserService {
return UserService{}
}
func (s *UserService) GetUserForKey(users map[string]User, key string) (User, error) {
return users[key]
}
Enums
Enums representing consecutive numbers starting from 0 are serializable
- TypeScript
- Go
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;
}
}
}
Currently not supported. Coming soon!
Unions
- TypeScript
- Go
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;
}
}
Not supported.
"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.
- TypeScript
- Go
any
interface{}