Lorenz Henk

Full Stack Developer

Storybook with create-react-app and Typescript

# generate a new app using create-react-app
yarn create react-app my-app --typescript
cd my-app

# install storybook cli
yarn add -D @storybook/cli

# initialize with storybook cli
yarn sb init

yarn sb init should not be called with the --type react flag. Without --type, the cli figures out the correct type on its own.

The correct type for an app created with create-react-app is react_scripts.

Check out the source code for available types.


Typescript generic with union

Click here to see the initial setup
enum MessageTypes {
  Success,
  DuplicateEmail,
}

interface ContentMapping {
  [MessageTypes.Success]: {
    data: any;
  };
  [MessageTypes.DuplicateEmail]: {
    email: string;
  };
}

interface Message<Type extends MessageTypes> {
  type: Type;
  content: ContentMapping[Type];
}

We'll compare the following two types:

type Option1 = Message<MessageTypes.DuplicateEmail | MessageTypes.Success>;

type Option2 =
  | Message<MessageTypes.DuplicateEmail>
  | Message<MessageTypes.Success>;
Let's substitute Message and ContentMapping
type Option1 = {
  type: MessageTypes.DuplicateEmail | MessageTypes.Success;
  content:
    | {
        data: any;
      }
    | {
        email: string;
      };
};

type Option2 =
  | {
      type: MessageTypes.DuplicateEmail;
      content: {
        email: string;
      };
    }
  | {
      type: MessageTypes.Success;
      content: {
        data: any;
      };
    };

In Option1, type and content are not connected. A malformed Message can be created:

const message: Option1 = {
  type: MessageTypes.DuplicateEmail,
  content: {
    data: "This should not be allowed!",
  },
};

On the other hand, Option2 throws an error:

const message2: Option2 = {
  type: MessageTypes.DuplicateEmail,
  content: {
    data: "This *is* not allowed!",
  },
};

Property 'email' is missing in type '{ data: string; }' but required in type '{ email: string; }'.

Check out this TypeScript playground for a live demo.


Typescript module declarations are ignored

You can write custom type definitions for a module in .d.ts files, for example:

// some-name.d.ts

// my-module will have the type `any`
declare module "my-module";

// specify the exports
declare module "my-other-module" {
  export function foo(bar: number): string;
}

.d.ts files should be in the src directory.

With tsc, this file is included globally.

Starting with version 7 of ts-node, .d.ts files are not included automatically.

Injecting TS_NODE_FILES=true tells ts-node to include the files as well.

See here for more information.


Change default shell for new users

If you have a system with lots of new users, you probably want to set the default shell to the one that most users prefer.

If you're using the useradd command, you can set default options in the file /etc/default/useradd.

Editing this file can be done by using useradd -D ...:

# set default shell for new users to bash
useradd -D -s /bin/bash

Check here for more information.


Convert JSON to table type

The function json_populate_record can be used to cast a JSON object to a table type:

CREATE TABLE foo(bar int);

SELECT  *
FROM    json_populate_record(NULL::foo, '{"bar": 42}')
+-------+
| bar   |
|-------|
| 42    |
+-------+

This can also be used to insert into the table:

INSERT INTO foo
SELECT *
FROM   json_populate_record(NULL::foo, '{"bar": 42}')

Use multiple files for docker-compose config

You can specify one or multiple config files for docker-compose with the -f flag:

# one file
docker-compose -f docker-compose.yml up -d
# multiple files
docker-compose -f docker-compose.yml -f docker-compose.tests.yml up -d

Be sure to specify the config files before the sub-command:

# invalid
docker-compose ps -f docker-compose.yml
# valid
docker-compose -f docker-compose.yml ps

Get granted roles with psql

With psql, there is an easy way to check which roles are granted to a role: \du

henk=> CREATE ROLE accounting;
CREATE ROLE
henk=> CREATE ROLE alex;
CREATE ROLE
henk=> GRANT accounting TO alex;
GRANT ROLE
henk=> \du accounting
             List of roles
 Role name  |  Attributes  | Member of
------------+--------------+-----------
 accounting | Cannot login | {}

henk=> \du alex
              List of roles
 Role name |  Attributes  |  Member of
-----------+--------------+--------------
 alex      |              | {accounting}