0

I'm working with the rpi-led-matrix repo to successfully control an LED panel. While it has been super helpful in getting hardware controlled via TypeScript, I'm struggling a bit with its multiple inline union types when attempting to validate my own unknown/string environment variables.

This example works so far when setting the number of LED panel rows option. No validation yet:

config.ts

import * as dotenv from 'dotenv'
import { LedMatrix, MatrixOptions } from 'rpi-led-matrix'

dotenv.config({ path: `${__dirname}/.env` })

export const matrixOptions: MatrixOptions = {
  ...LedMatrix.defaultMatrixOptions(),
  rows: process.env.MATRIX_ROWS
    ? <16 | 32 | 64>Number(process.env.MATRIX_ROWS)
    : LedMatrix.defaultMatrixOptions().rows,
}

To better handle validation and communicate any issues in console, I'm trying to break this out into a utils file:

configUtils.ts

const matrixRowOptions = [16, 32, 64]
type MatrixRowOptions = typeof matrixRowOptions[number]

export const configMatrixRows = (
  configRows?: string | number,
): MatrixRowOptions => {
  const rows = Number(configRows) as MatrixRowOptions
  if (matrixRowOptions.includes(rows)) {
    return rows
  }

  if (rows) {
    console.error(
      `supplied rows value of ${rows} is not a valid option, assigning default of ${
        LedMatrix.defaultMatrixOptions().rows
      }.`,
    )
  }

  return LedMatrix.defaultMatrixOptions().rows
}

new config.ts:

import * as dotenv from 'dotenv'
import { LedMatrix, MatrixOptions } from 'rpi-led-matrix'
import { configMatrixRows } from './configUtils';

dotenv.config({ path: `${__dirname}/.env` })

export const matrixOptions: MatrixOptions = {
  ...LedMatrix.defaultMatrixOptions(),
  rows: configMatrixRows(process.env.MATRIX_ROWS), // <<<  not happy
}

TypeScript Error:

Type 'number' is not assignable to type '16 | 32 | 64'.ts(2322)
types.d.ts(207, 5): The expected type comes from property 'rows' which is declared here on type 'MatrixOptions'

I'm missing something. How do I resolve the error and successfully validate unknown data for the inline union type? I've pulled initial inspiration from this Stackoverflow question, however it's not quite hitting the mark yet.

Christopher Stevens
  • 1,214
  • 17
  • 32

1 Answers1

1

This happening because the type MatrixRowOptions is just number. This makes the return type of configMatrixRows just number as well, which will lead to the error since number is wider than 16 | 32 | 64.

So why is the type of MatrixRowOptions number?

Because the type of the variable matrixRowOptions is also just number[]. So typeof matrixRowOptions[number] will resolve to number.

You have to convert matrixRowOptions to a tuple with the three elements 16, 32 and 64. For that we use as const.

const matrixRowOptions = [16, 32, 64] as const

Playground

Tobias S.
  • 21,159
  • 4
  • 27
  • 45