My TypeScript cheat-sheet

Photo by Web Donut on Unsplash
Refill!

TypeScript became essential part of my professional activity. It got to the point that if I see pure JavaScript code, I simply can't acknowledge that. I immediately start asking myself "How is that possible for a language to not to have types?".

There are some tips and tricks I don't use quite often, so I decided to write down some notes, so I could always have them available.

Extend one complex type from another

I am not a huge fan of interfaces and inheritance, since there is plenty of ways to create a derivative type, via "union" and a few extra tricks:

type CarType = {
speed: number;
color: string;
model: string;
};
// Add a subset of properties from CarType
type PlaneTypeA = {
class: string
} & Pick<CarType, 'speed' | 'model'>;
// Add one property from CarType
type PlaneType = {
class: string;
speed: CarType["speed"];
};
// "Inherit" type
type SuperCarType = {
super: boolean;
} & CarType;

Typing static class methods

Not a huge sucker for OOP either, but occasionally I have to deal with it. So,

interface CommandProcessorInstance {}
export interface CommandProcessor {
new (): CommandProcessorInstance;
attach(program: CommanderCommand): void;
process(args?: CommandActionArguments): Promise<void>;
}
export function Implements<T>() {
return <U extends T>(constructor: U) => {
// eslint-disable-next-line no-unused-expressions
constructor;
};
}
@Implements<CommandProcessor>()
export class CommandRun {
public static attach(
program: CommanderCommand,
) {
// ...
}
public static async process(
args: CommandActionArguments,
) {
// ...
}
}

Indexed vs Mapped Object vs Record

type MyMappedObjectType = {
[k in string | number]: unknown;
};
type MyIndexedType = {
[k: string]: unknown;
};
type MyRecord = Record<string, unknown>;

Assign argument types

If I have multiple functions of the same signature, I don't have to specify argument types every time. Instead, I make a type declaration once and just assign it to many functions. TS is smart enough to figure argument types in this case.

type SomeFunctionType = (foo: number, bar: string, baz: boolean) => void;
const funA: SomeFunctionType = (a, b, c) => { ... };
const funB: SomeFunctionType = (a, b, c) => { ... };
const funC: SomeFunctionType = (a, b, c) => { ... };

Create types from types

Generics

It is possible to use generics to make a dependency between types of function arguments:

function pluck<T, K extends keyof T>(o: T, propertyNames: K[]): T[K][] {
return propertyNames.map((n) => o[n]);
}

Typeof

Sometimes I can't import types from a third-party library, or I simply don't have types explicitly defined. Nevertheless, there is a way to declare a variable to be of the same type as the other variable:

const data = [
{ name: 'Alex', position: 'pilot' },
{ name: 'Amos', position: 'tech' },
];
const crewMember: typeof data[0] | undefined;

No rest for an engineer, so, yeh, to be continued...

Sergei Gannochenko

Business-oriented fullstack engineer, in ❤️ with Tech.
React, Node, Docker, AWS, Jamstack.
15+ years in dev.