Nerd For Tech
Published in

Nerd For Tech

Matt’s Tidbits #95 — Defining constants in TypeScript

Last time I wrote about how to write safe enums in TypeScript. This week’s tidbit is also TypeScript related — how to define constants!

Defining a constant in TypeScript can be pretty simple — you can just write something like . However, that keyword only works if you’re defining variables at file-scope or inside a function. What if you want to group your constants under some kind of named object (as is common in other languages such as Java, C++, etc.)

The obvious way (and what I did to start), was simply to define an object to contain my constants, like this:

const NamedVariables = {
SOME_CONSTANT_1: "FOO",
SOME_CONSTANT_2: 42,
DEFAULT_FONT_WEIGHT: "700",
};

This allows me to use this like this: . Great!

However, there’s one tiny gotcha. This works fine for some situations, but in cases where TypeScript is expecting a value that’s part of a union type, such as specifying the property of a , you may see an error such as this:

Type 'string' is not assignable to type '"normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900" | undefined'.

If you’re like me, you might scratch your head over this for quite a while. Until you realize (do some fervent Google searching) that Object properties are not constant by default.

The in above means that the reference to that object is constant — so it would be illegal to do something like after it’s already been defined. Which is good — we definitely don’t want someone to reassign our constants object. But how can we define its properties as constant?

The first thing I found is to use — this returns an object whose properties are read-only. So, if we try this with our example:

const NamedVariables = Object.freeze({
SOME_CONSTANT_1: "FOO",
SOME_CONSTANT_2: 42,
DEFAULT_FONT_WEIGHT: "700",
});

Unfortunately, this STILL doesn’t work if we try to use in a union type. Why is this? As best as I can understand, it’s because TypeScript doesn’t recognize this as a true constant — Object.freeze() makes use of some somewhat crazy runtime checks that throw an error if you try to modify it. So, chalk this one up to a limitation (maybe temporary? maybe permanent?) of TypeScript.

So… is there any way to achieve this? The good news is, yes!

Here’s how we can make all properties on an object be treated as constants:

const NamedVariables = {
SOME_CONSTANT_1: "FOO",
SOME_CONSTANT_2: 42,
DEFAULT_FONT_WEIGHT: "700",
} as const;

That’s it — those two little keywords at the end — are a TypeScript addition (not part of JavaScript) that instruct the type checker that all properties on an object should be treated as constants.

I highly recommend adding this to all of your Objects that you intend to be constants. Let the type system help you!

Do you define constants differently? I’d love to hear from you in the comments!

Interested in working with me in the awesome Digital Products team here at Accenture? We’re hiring!

--

--

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store