Most recent blog posts

Or you can click on the categories to filter by topic

Object.keys to return the known strings of an object in TypeScript

October 25, 2024
0 comments JavaScript

This one always confused me but by blogging about it, hopefully, it will stick.

This does NOT work in TypeScript:


const person = {
  firstName: "peter",
  lastName: "bengtsson",
  state: "happy"
}

const keys = Object.keys(person)
const randomKey = keys[Math.floor(Math.random() * keys.length)];
const value = person[randomKey]

It works in JavaScript, but in TypeScript you get an error on the last line (from the person[randomKey]):

Truncated! Read the rest by clicking the link below.

How I make my Vite dev server experience faster

October 22, 2024
0 comments React, Node, JavaScript

I have a web app that operates as a SPA (Single Page App). It's built on regular Vite + React + TypeScript. In production you just host the built static assets, but in development (for hot module reloading and stuff) I use the built-in dev server in Vite. This is what you get when you type vite without any other command line arguments.

But here's what happens, you're in the terminal and you type npm run dev and hit Enter. Then, using your trackpad or keyboard shortcuts you switch over to a browser tab and go to http://localhost:5173/. When you get there to the first request, Vite starts at the entry point, which is src/main.tsx and from there, it looks at its imports and starts transpiling the files needed. You can see what happens with vite --debug transform.

With debug:

Truncated! Read the rest by clicking the link below.

How to extend a function in TypeScript without repeating the signature types

October 16, 2024
0 comments JavaScript

Suppose you have a function, written in TypeScript, that is fine and complete. Now you want to write a function that works like that one but with just some slightly more parameters and other differences. It's not too different from a decorator function.

Extending the list of parameters

Let's imagine that you already have this function:


type Operation = "sum" | "sub" | "mul" | "div"

function calculator(a: number, b: number, op: Operation) {
  if (op === "sum") return a + b
  if (op === "sub") return a - b
  if (op === "mul") return a * b
  if (op === "div") return a / b
  throw new Error(op)
}

And this could, for the sake of argument, be in a different file and/or possibly outside your control. What you now want to do is write a new function that takes those same arguments, plus one more. And importantly, you don't want to have to spell out all the arguments one more time.

First, the WRONG way to solve this:


import { calculator } from './calculator' // The code in the snippet above

type Operation = "sum" | "sub" | "mul" | "div"

function doubleCalculator(a: number, b: number, op: Operation, c: number) {
  return calculator(calculator(a, b, op), c, op)
}

console.log(calculator(1, 2, "sum")) // 3
console.log(doubleCalculator(1, 2, "sum", 10)) // 13

Technically, it works, but you had to repeat the calculator function's signature.

Truncated! Read the rest by clicking the link below.

Trying out the new Bun "Compile to bytecode"

October 15, 2024
0 comments Bun, JavaScript

Bun 1.1.30 came out last week. What got me intrigued is this new option to bun build which is --bytecode. With it you can create an executable, supposedly compiled partially to bytecode which means it can start even faster.

I tried it on my hylite CLI which is a CLI, built with Bun, but works in all versions of Node, that can syntax highlight code to HTML on the command line. Here's what I did:

Truncated! Read the rest by clicking the link below.

The performance benefits of code-split an SPA

October 12, 2024
0 comments React

This isn't a comprehensive in-depth analysis but I have this SPA which is built with Vite + React.
When you run npm run build it produces:

vite v5.4.8 building for production...
✓ 8210 modules transformed.
dist/index.html                             0.76 kB │ gzip:   0.43 kB
dist/assets/images-xTxpPavl.css             2.02 kB │ gzip:   0.55 kB
dist/assets/index-IHK6QBxo.css            200.12 kB │ gzip:  29.85 kB
dist/assets/index-jgmGYYS9.js               0.79 kB │ gzip:   0.51 kB
dist/assets/open-graph-image-Ca6hLYnz.js    1.47 kB │ gzip:   0.82 kB
dist/assets/images-CwbhV2EW.js             28.75 kB │ gzip:  10.37 kB
dist/assets/pageviews-C6NSq649.js         378.67 kB │ gzip: 106.42 kB
dist/assets/index-HpyQl1NK.js             490.15 kB │ gzip: 154.11 kB
✓ built in 4.46s

Truncated! Read the rest by clicking the link below.

Rate my golf swing (October 2024)

October 11, 2024
0 comments Golf

Last time I uploaded a video was only a few months ago but one thing that I've improved, since that video, is the wrist alignment at the top of the swing. Neither video does a perfect job of showing this but it's a least a bit better now.

Top of swing highlighted

I think what I still have to work on to slow down, and find a smooth and slow tempo, as the club travels up in the back swing.

The 3 queries I use with pg_stat_statements to analyze slow PostgreSQL queries

September 30, 2024
0 comments PostgreSQL

pg_stat_statements is a contributed extension for PostgreSQL that logs all queries and how long they took. If you aggregate on this, you can determine where your PostgreSQL spends the most time and what to optimize.

How it works and how you install it is for another blog post.

Total time


SELECT
  (total_time / 1000 / 60) AS total,
    (total_time/calls) AS avg, calls,
      SUBSTRING(query FROM 0 FOR 250)
      FROM pg_stat_statements
      WHERE calls > 100
      ORDER BY 1 DESC
      LIMIT 25;

This one is important because you could have some terribly slow query that uses lots of sequential scans, but perhaps it's only used once a week, so who cares?

Truncated! Read the rest by clicking the link below.

How to handle success and failure in @tanstack/react-query useQuery hook

September 16, 2024
0 comments React, JavaScript

What @tanstack/react-query is is a fancy way of fetching data, on the client, in a React app.

Simplified primer by example; instead of...


function MyComponent() {
  const [userInfo, setUserInfo] = useState(null)
  useEffect(() => {
    fetch('/api/user/info')
    .then(response => response.json())
    .then(data => {
      setUserInfo(data)
    })
  }, [])

  return <div>Username: {userInfo ? userInfo.user_name : <em>not yet known</em>}</div>
}

Truncated! Read the rest by clicking the link below.

swr compared to @tanstack/react-query

August 30, 2024
2 comments JavaScript

I have a single-page-app built with React and Vite. It fetches data entirely on the client-side after it has started up. So there's no server at play other than the server that hosts the static assets.
Until yesterday, the app was use swr to fetch data, now it's using @tanstack/react-query instead. Why? Because I'm curious. This blog post attempts to jot down some of the difference and contrasts.

If you want to jump straight to the port diff, look at this commit: https://github.com/peterbe/analytics-peterbecom/pull/47/commits/eac4f873303bfb493320b0b4aa0f5f6ba133001a

Bundle phobia

When @tanstack/react-query first came out, back in the day when it was called React Query, I looked into it and immediately got scared how large it was. I think they've done some great work to remedy that because it's now not much larger than swr. Perhaps it's because swr, since wayback when, has grown too.

When I run npm run build it spits this out:

Truncated! Read the rest by clicking the link below.

Previous page
Next page