TypeScript Best Practices

Anh-Thi Dinh
draft
⚠️
This is a quick & dirty draft, for me only!

References

General Types

Don’t use the types Number, String, Boolean, Symbol or Object.
1// Do
2function reverse(s: string): string;
1// Don't
2function reverse(s; String): String;
Don’t use generic type T if you don’t use it! (More)
1// Do
2interface Named<T> {
3  name: string;
4  value: T; // <-- added
5}
1// Don't
2interface Named<T> {
3  name: string;
4}
Don’t use any. At least, use unknown.

Callback Types

Don’t return any for callbacks whose value will be ignored.
1// Do
2// It prevents you from accidentally using the return value of x.
3function fn(x: () => void) {
4	x();
5}
1// Don't
2function fn(x: () => any) {
3  x();
4}
It’s always legal to provide a callback that accepts fewer args. So, don’t use optional params in callbacks.
1// Do
2interface Fetcher {
3  getObject(done: (data: unknown, elapsedTime: number) => void): void;
4}
1// Don't
2interface Fetcher {
3  getObject(done: (data: unknown, elapsedTime?: number) => void): void;
4}
Don’t overload callbacks.
1// Do
2declare function beforeAll(
3  action: (done: DoneFn) => void,
4  timeout?: number
5): void;
1// Don't
2declare function beforeAll(action: () => void, timeout?: number): void;
3declare function beforeAll(
4  action: (done: DoneFn) => void,
5  timeout?: number
6): void;

Function Overloads

Don’t put more general overloads before more specific overloads → TS uses the first matching overload.
1// Do
2declare function fn(x: HTMLElement): number;
3declare function fn(x: unknown): unknown;
1// Don't
2declare function fn(x: unknown): unknown;
3declare function fn(x: HTMLElement): number;
Use trailing params instead of overloads.
1// Do
2interface Example {
3  diff(one: string, two?: string, three?: boolean): number;
4}
1// Don't
2interface Example {
3  diff(one: string): number;
4  diff(one: string, two: string): number;
5  diff(one: string, two: string, three: boolean): number;
6}
Don’t write overloads that differ by type in only one argument position.
1// Do
2interface Moment {
3  utcOffset(b: number | string): Moment;
4}
1// Don't
2interface Moment {
3  utcOffset(b: number): Moment;
4  utcOffset(b: string): Moment;
5}
To be continued…