Programming

Curl a GraphQL API

Programming GraphQL CommandLine

curl -0 -v -X POST https://some.api.com/graphql \ -H 'Content-Type: application/json' \ -d @- << EOF { "query": "query { someQuery (someArg: false) { name } }" } EOF curl will probably complain about the -X POST being inferred, but it shouldn’t harm anything. It can be left out.

Function Overloading

TypeScript Programming

Take a function like below… type Combinable = string | number function add(a: Combinable, b: Combinable): Combinable { if (typeof a === 'string' || typeof b === 'string') { return a.toString() + b.toString() } return a + b } If we were to use this function like this: const x = add('black cat', 'white dog') x.split(' ') // TS compiler will complain here TypeScript cannot determine what the return type of add is at this point. ...

Nullish Coalescing

TypeScript Programming

// say you have some var hangin' around called `name` let x: string = name ?? '(no name)' ?? is the nullish coalescing operator. It differs from || in that if you had (in the above example) let x: string = name || '(no name)' name equal to an empty string (which is falsey) x would then be assigned the value (no name). The nullish coalescing operator will only use the right-hand assignment for “nullish” values (null or undefined). ...

Recursive Type Aliases

TypeScript Programming

In TS@4 a type can reference itself, e.g. type JSONValue = | string | number | boolean | null | JSONValue[] | { [k: string]: JSONValue } Previously, this would not be possible without some messy hacks.

Labeled Tuple Types

TypeScript Programming

type Address = [number, string, string, number] Say you now have a function printAddress which takes an Address type as its arg. function printAddress(...address: Address) { // ...stuff } Your editor (before TS@4) would hint that the arguments were something like: address_0: number, address_1: string, ...etc which is not really helpful because address_0: number doesn’t really explain what that parameter corresponds to. With Labled Tuple Types we can do type Address = [streetNumber: number, city: string, state: string, zip: number] NOTE: once you begin to label an element in a type definition, you must label all of the other elements. ...

Variadic Tuple Types

TypeScript Programming

type Foo<T extends any[]> = [boolean, ...T, boolean] Before TS@4.0 ...T would need to be the last element, but now we can spread the T type nested between known types; e.g. “This array will have a boolean, with some stuff (strings, numbers, etc.), and another boolean”.

Composite Builds

TypeScript Programming Monorepo

TypeScript has a way of describing a build process as multiple subpieces of a project. This saves from having to build every piece, and instead build independent parts and stitch them together as needed. In a monorepo environment, multiple packages will have multiple builds and, possibly, refer to those builds amongst each other. The root tsconfig.json file can be used, but a problem of independent sources of truth arises. For instance, one project may have a different level of type strictness, or use a different version of Node. ...

Jest Setup for a Monorepo

Programming Jest Monorepo

Out of the box, Jest mostly works in a Monorepo environment, with the exception of a few Babel plugins so that (as an example) TypeScript works. Needs: @babel/preset-env (Babel will transform whatever it needs to transform based on the build target, e.g. TypeScript, IE11, ES6, Node10, etc.) @babel/preset-typescript (Babel will strip out the symbols that are specific to TypeScript) The root-level .babelrc file would look like: { "presets": [ ["@babel/preset-env", { "targets": { "node": 10 } }], "@babel/preset-typescript" ] } The target above is arbitrary, and can be anything (or nothing). ...

Colocation

Programming GraphQL

“colocation” is a pattern wherein you keep the query/mutation as close to the consuming component as possible. In many instances, it’s in the exact file. This is in contrast with the DRY approach, which would beg the author to push queries/mutations higher up and imported into whichever file needs it.