Saturday, 19 January 2019

Void as a Generic Type

TypeScript allows you to use void as a generic type. I mean, you can declare a Promise<void> (the Promise resolves to no value) or an Observable<void> (the Observer gets called with no value). I first made use of this feature copy/pasting and adapting some code, so did not give it much importance, but later on when writing code from scratch it's when I realised that this <void> thing was indeed something new to me as it does not exist in C# (the main language with generic types that I work with).

In C#, where void as a generic type is not allowed, we have 2 different types, Task<TResult> and Task. Task<TResult> is used for returning a value (it has a Result property) while Task is used when no value is going to be returned (it lacks a Return property). So I saw myself with the confusion of whether my TypeScript function returning a Promise that resolves to no value should return just a Promise or a Promise<void>. Well, both compile OK, but Promise<void> has a much clearer semantic.

//promise resolving to no value
let p = new Promise((res, rej) => res()); 

let p1 = new Promise<void>((res, rej) => res()); 

//promise resolving to string
let p2 = new Promise((res, rej) => res("hi"));

let p3 = new Promise<string>((res, rej) => res("hi"));


//this one, compiles OK, it's supposed to resolve to a string but I resolve to no value
let p4 = new Promise<string>((res, rej) => res());

 //but this one gives a compiler error
//let p5 = new Promise<void>((res, rej) => res("hi"));

Thing is slightly different for Observables. For those sending no value to their Observers we have to use Observable<T>. The TypeScript compiler does not allow us to use a non generic Observable type. Seems a bit odd to me, Obviously at JavaScript level we have an Observable class, but it seems like the type definition file for Observables has been done only for Observable<T> and not for Observable.

function f1():Observable<void> {
    return of();
}

//compiler error
// function f2():Observable<void> {
//     return of("string");
// }

function f3():Observable<string> {
    return of("hi");
}

function f4():Observable<string> {
    return of();
}