Skip to content

Instantly share code, notes, and snippets.

Created Jul 31, 2020
What would you like to do?

Table of contents

  1. Type vs. Interface
  2. Enums
  3. Object, object & {}
  4. Type guards
  5. Type assertions
  6. Implicit vs. explicit typing
  7. Generics vs. any vs. unknown
  8. File Names
  9. Casing and naming conventions
  11. Redux

Type vs. Interface

What's the difference?


When to use interface?

  • Whenever you can 😉 Why?
    • Declaration merging,
    • Extending is safer than intersections. You won't accidentally override a property.

When to use type?

  • When you want to alias something in the scope of the particular file.
  • When you are not exporting the particular type.
  • You need a union type.
  • When you need mapped types.


Don't use enums.


  • Come with a huge variation surface (numeric, string-based, manually counted, automatically counted, inline, dynamic, one-directional, bi-directional).
  • Create bloated objects in runtime.
  • Produce unexpected results because of merging (two of the same name can live in one scope)
  • Consider the following example:
enum Status { 
  a = 1,
  b = 2,
  c = 3,

const foo = (x: Status)  => console.log(x);
foo(100); // ok, no error

What to use instead?

  • String literal types: type State = "loading" | "error" | "initial"
  • Numeric literal types: type State = 1 | 2 | 3

You can read more about how enums work here.

Object, object & {}

Don't use {}


  • {} is the empty type and is assignable from any non-null/non-undefined type.
  • It allows extra properties: const obj: {} = { size: 10 } // OK.
  • It allows primitives: const obj: {} = "hello" // OK.

Don't use Object


Don’t ever use the types Number, String, Boolean, Symbol, or Object These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code.

Use object or <T extends object>


const foo = (x: Object) => null;
const foo = (x: {}) => null;


const foo = (x: object) => null;
const foo = <T extends object>(x: T, key: keyof T) => null;

Type guards

  • Use type guards wherever for every predicate that is checking the type. (Prefer type guard instead of usual predicates where applicable.)
  • Use unknown for the parameter type.
  • It allows TypeScript to narrow the type correctly.


const isUser = (x: unknown) => x && && x.age;

// x is of type unknown
if (isUser(x)) {
  // x is still of type unknown


const isUser = (x: unknown): x is User => x && && x.age;

// x is of type unknown
if (isUser(x)) {
  // x is of type User

Type assertions

Use as for type assertions. Why?

  • Consistency,
  • <type>value is often associated with type casts in other languages.


const env = <string>process.env.NODE_ENV;


const env = process.env.NODE_ENV as string;

Implicit vs. explicit typing

Let the TypeScript compiler infer as much as possible and avoid defining types when it is unnecessary.


const trim = (x: string): string => x.trim();

const x: number = 10;


const trim = (x: string) => x.trim();

const x = 10;

Generics vs. any vs. unknown

Type parameters should be used to enforce constraints between types.

  • capture the relationship between function arguments and its return type
  • capture the relationship between the class type and its properties and methods

Type parameters should always describe a relationship.


// type parameter is only used once
declare const doSomething = <T>(x: T): void;

// type parameter is not used to define any parameter
declare const parse = <T>(): T;
const x = parse<string>();

// any is unsafe and "turns off" type checking
declare const parse = (): any;
const x = parse();


declare const doSomething = (x: unknown): void;

declare const parse = (): unknown;
const x = parse() as number;

Use one-letter type parameters names


type Transform<InputProps, OutputProps> = (props: InputProps) => OutputProps


type Transform<A, B> = (props: A) => B


  • It makes the type reusable,
  • Expressed the generic nature of the function.

If you have too many type parameters that one-letter names are hard to read, then you have too many type parameters.

File names

Use PascalCase for React components (if the file's main export is React component), and camelCase otherwise.

Casing and naming conventions

Use camelCase for variable and function names.


const FooBar = '';


const fooBar = '';

Use PascalCase for classes, type aliases, and interfaces and camelCase for members.


type foo = string;
interface bar {
  Name: string
class component { }


type Foo = string;
interface Bar {
  name: string
class Component { }

Don't prefix interfaces with I.


interface IRequest {}


interface Request {}


Make sure your comments are meaningful.


// we are setting counter to 0
const counter = 0;


const counter = 0;

If you are documenting a function behavior consider using JSDoc format.


 * This is a function.
 * @example
 *  foo('hello')

function foo(n: string) { return n }

It's okay to leave todo comments.

interface State {
  items: any; // todo — dependent on X/requires Y to type correctly


How to type actions and actions creators?

// service/types.ts
export const INSERT_REQUEST = 'INSERT_REQUEST' as const;
export const UPDATE_REQUEST = 'UPDATE_REQUEST' as const;

const insert = (payload: string) => ({

const update = (payload: { id: number }) => ({

export type ActionTypes = ReturnType<typeof insert | typeof update>;

How to type connect HOC?

import { connect, ConnectedProps } from 'react-redux'

const mapState = (state: RootState) => ({
  tables: state.tables

const mapDispatch = {
  setTableName: (name: string) => ({ type: 'SET_TABLE_NAME', name })

const connector = connect(mapState, mapDispatch)

interface Props extends ConnectedProps<typeof connector> {
  tableName: string

const MyComponent: React.FC<Props> = props => (
    <input onChange={e => props.setTableName(} type="text" />
    { => (<p></p>))}

export default connector(MyComponent)

How to type reducers?

Follow this documentation

How to use TypeScript with Redux Thunk?

Follow this documentation.


This comment has been minimized.

Copy link

@lautapercuspain lautapercuspain commented Aug 1, 2020

Great reference doc! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment