Constants, interfaces and types
Table of Contents
:ID: 2CCE3E8C-7B7B-4050-BABF-59F788C94383
See also Index signature
# const
Assertions
Using as const
lets you define literal values.
- For objects the keys are
readonly
- Arrays become
readonly
tuples.
const THINGS = { thing1: 1, thing2: 2 } as const
# With types
Here’s one problem I had. This trivial example demonstrates it. Doing something like this…
const thingName = Object.keys(THINGS).find((name) => { return THINGS[name] === 1 });
…TypeScript will fail to compile with this error:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly thing1: 1; readonly thing2: 4; }'. No index signature with a parameter of type 'string' was found on type '{ readonly thing1: 1; readonly thing2: 4; }'.
OK, so we have literal values here and TypeScript doesn’t know what the name
local variable is. To get around this, I defined a union type out of the
constants keys.
# typeof
type ThingName = keyof typeof THINGS; // 'thing1' | 'thing2'
Then, using a type assertion on the name
, satisfied the compiler:
const thingName = Object.keys(THINGS).find((name) => { return THINGS[name as ThingName] === 1 });
With an Array const:
const things = ['thing1', 'thing2'] as const; type thing = typeof things[number];
See also https://stackoverflow.com/a/55505556
# valueof
There isn’t a valueof
, but a helper type can be created to accomplish
that:
type ValueOf<T> = T[keyof T] type ValueOfThings = ValueOf<Things>; // 1 | 2
See also https://stackoverflow.com/a/49286056
# With Record
utility type
I didn’t actually do this, but it looks like it’s possible to use a Record type if I really wanted to get crazy with it.
type ThingName = 'thing1' | 'thing2' type ThingId = 1 | 2 export const THINGS: Record<ThingName, ThingId> = { thing1: 1, thing2: 2 } as const