Creating singletons in node.js
Nodejs modules are singletons
Read moreType guards in TypeScript are special functions which are used to detect if any
or unknown
types are of a certain type.
How many times did you checked if a variable is a string
or a number
? Well, stop doing it by hand everytime, use type guards!
Being functions, those type checks are reusable and will prevent you from explicitely type cast anything in your code, leaving everything cleaner and easier to maintain and reuse.
Well, TypeScript is a superset of JavaScript, isn't is? JavaScript, since is dinamically typed, could be quite dangerous if you do not type checking.
Type checking is one of the most boring and usually messier part of any codebase.
Type guards can help you by reducing your code base and reusing every type check you make.
Instead of writing checks like this every time, which mess up your code
interface User {
name: string;
surname: string;
}
function fullName(arg: unknown): string {
if (typeof arg === 'object' && arg !== null && 'name' in arg && 'surname' in arg) {
const name = typeof (<User> arg).name === 'string' ? (<User> arg).name : '';
const surname = typeof (<User> arg).surname === 'string' ? (<User> arg).name : '';
return [name, surname].concat(' ');
}
return 'unknown';
}
use a type guard like this!
interface User {
name: string;
surname: string;
}
function isUser(arg: unknown): arg is User {
return (
typeof arg === 'object' &&
arg !== null &&
'name' in arg &&
'surname' in arg
);
}
function isString(arg: unknown): arg is string {
return typeof arg === 'string';
}
function fullName(arg: unknown): string {
if (isUser(arg)) {
const name = isString(arg.name) ? arg.name : '';
const surname = isString(arg.surname) ? arg.name : '';
return [name, surname].concat(' ');
}
return 'unknown';
}
Great, cleaner and more reusable code!
Note that everytime you will have to do a check on a type implementing the User
interface, you will have only to use the proper type guard function!
You can of course write advanced typeguards for more structured data in order to grant if a variable is of a type or not.
For example you could check if a variable is a Person
like this
// primitive-typeguards.ts
export function isNumber(arg: unknown): arg is number {
return typeof arg === 'number';
}
export function isString(arg: unknown): arg is string {
return typeof arg === 'string';
}
// Person.ts
import { isNumber, isString } from './primitive-typeguards';
export interface Person {
age: number;
name: string;
}
export function isPerson(arg: unknown): arg is Person {
return (
typeof arg === 'object' &&
'age' in arg &&
'name' in arg &&
isNumber((arg as any).age) &&
isString((arg as any).name)
);
}
// app.ts
import * as person from './Person';
export default function getPerson(surname: string, name: string): Promise<person.Person | null> {
const json = await (await fetch(`endpoint/${surname}/${name}`)).json();
return person.isPerson(json) ? json : null;
}
When you write your application using Domain Driven Development (aka DDD), it's a good practice to add, inside your entity's file, the proper type guards functions.
Another example for you
export interface User {
name: string;
surname: string;
}
export type t = User;
export const make = (partial: Partial<t> = {}): t => ({
name: partial.name ?? '',
surname: partial.surname ?? '',
})
export const guard = (arg: unknown): arg is t => (
typeof arg === 'object' &&
arg !== null &&
'name' in arg &&
'surname' in arg
)
Nodejs modules are singletons
Read moreBored of checking incoming JSON data from clients? Try with a middleware and typeguards!
Read moreWhat if we are making a great mistake? Finding value where there is some.
Read more