Skip to content

Instantly share code, notes, and snippets.

@bozhanglab49
bozhanglab49 / use-ref-hook.md
Last active September 28, 2021 02:15
TWL-Lab49/How React useRef hook perfectly solves our problem

In my previous project, we had been plagued by a UI bug for quite some time. Every time it popped up in production, we escalated the issue a bit. Then it was indeed mitigated by some patch fixing. But the issue was always lurking and could still come back and bite us anytime. Finally, we decided to dedicate a whole sprint to get to the bottom of the issue.

The Problem

The app has some tabs which share some parent components. When switching the tabs, it updates some states in parent components. The issue is when switching too fast, the states in tabs are somehow messed up and thus data is corrupted. After a sprint's thorough looking, it boils down to this piece of code:

useEffect(() => {
  getPreferences(sourceType).then(preferences => setPreferences(preferences));
}, [...]);

Pretty simple code, but the big issue with this is when the tabs are switched too fast, by the time the Promise resolves, the sourceType is updated and the preferences is not valid anymore. Once this is figured out, the

@bozhanglab49
bozhanglab49 / lac-relative-path-terragrunt.md
Last active September 21, 2021 13:12
TWL-Lab49/Learning IaC - Relative Path in Terragrunt

One of the gotchas mentioned in Terragrunt doc is about Relative File Path. To summarize, this works:

terraform {
  source = "git::git@github.com:foo/modules.git//frontend-app?ref=v0.0.3"

  extra_arguments "custom_vars" {
    commands = [
      "apply",
 "plan",
@bozhanglab49
bozhanglab49 / bash-cat-command.md
Last active September 20, 2021 21:54
TWL-Lab49/Learning Bash - Cat Command

cat is one of the top bash commands and mostly used to view files without opening them:

foo@bar:~$ cat file1

But cat is more versatile than that. It can read/write from/to stdin/stdout/file/here doc. The full syntax is

cat [options] [parameter1: filename/stdin/heredoc] [parameter2: >>|>|pipe] [parameter3: filename/stdout]
  • parameter1: read-from; if not specified, defaults to stdin
  • parameter3: write-to; if not specified, defaults to stdout
@bozhanglab49
bozhanglab49 / typescript-discriminated-union.md
Last active July 5, 2021 01:34
TWL-Lab49/Learning TypeScript - Discriminated Union

Recently, we enhanced the type of a select component. Here is what its props looked like before:

type SelectProps = {
  isMultiple: boolean;
  value?: string;
  values?: string[];
  options: string[];
};
@bozhanglab49
bozhanglab49 / from-ES2019-flat.md
Last active March 15, 2021 03:35
TWL-Lab49/Learning TypeScript - All from ES2019 flat function...

The Problem

In the UI repo of my current project, we've been using lodash. One of the heavily used functions is _.flatten. It's working great. But it always feels not right when we have to strike more keys to get our work done.

import _ from 'lodash';

const getTradeIds = async (): Promise<string[]> => {
  const chunkedIds: string[][] = await fetchJson('/trade-ids');
  return _.flatten(chunkedIds);
};
@bozhanglab49
bozhanglab49 / no-enum.md
Last active February 27, 2021 05:01
TWL-Lab49/Learning TypeScript - No Enum Please!

This is contrary to other languages where enums are highly preferable over regular constants but in TypeScript, we have better alternatives to enums.

Drawbacks of enums

number-valued enums are not type safe

enum LogLevel {
  INFO,
  WARNING,
 DEBUG,
@bozhanglab49
bozhanglab49 / typescript-function-type.md
Last active January 30, 2021 15:42
TWL-Lab49/Learning TypeScript - Interface Function Type: is it redundant?

In TypeScript, we can type a function in following way:

let mySearch: (source: string, pattern: RegExp) => boolean;
mySearch('123', /\d+/);

The part (source: string, pattern: RegExp) => boolean is called a function type.

In addition to above, we can also use interface to type a function:

@bozhanglab49
bozhanglab49 / typescript-covariance-contravariance.md
Last active June 25, 2021 08:37
TWL-Lab49/Learning TypeScript - Co-variance and Contra-variance

In TypeScript's handbook about inference of Conditional Types, it has this:

Next, for each type variable introduced by an infer (more later) declaration within U collect a set of candidate types by inferring from T to U (using the same inference algorithm as type inference for generic functions). For a given infer type variable V, if any candidates were inferred from co-variant positions, the type inferred for V is a union of those candidates. Otherwise, if any candidates were inferred from contra-variant positions, the type inferred for V is an intersection of those candidates. Otherwise, the type inferred for V is never.

It throws out co-variant and contra-variant positions.

So, what are co-variant and contra-variant positions or in other words, what are co-variance and contra-variance?

[Here](https://en.wikipedia.org/wiki/Covariance_and_

@bozhanglab49
bozhanglab49 / typescript-type-distribution.md
Last active January 18, 2021 03:29
TWL-Lab49/Learning TypeScript - Type Distribution

In my previous post about jest enhancement, there is following piece of code:

export function expectThat<T>(actual: T): [T] extends [undefined] ? Result<T> :
    [T] extends [(...args: any[]) => any] ? FunctionResult<T> : Result<T> {
    return expect(actual) as any;
}

We might wonder what's the difference from code below:

export function expectThat(actual: T): T extends undefined ? Result :
@bozhanglab49
bozhanglab49 / ts-jest-type-enhancement.md
Last active January 18, 2021 03:30
TWL-Lab49/Learning TypeScript - Jest is great! However...

As for frontend testing, Jest is great, no question about it. But to make its apis backward compatible, Jest has to compromise on type constraints when it comes to assert functions in TypeScript.

const onChangeMock: (field: string, value: number) => void = jest.fn();
onChangeMock('abc', 1);

expect(onChangeMock).toHaveBeenCalledWith('abc');

This test fails with following message

Expected mock function to have been last called with: