Home > Net >  Template literal throws errors in some scenarios but not others
Template literal throws errors in some scenarios but not others

Time:05-25

As part of a code review a colleague recommended using a type rather than an enum. Whilst making the changes we found an issue neither of us expected.

We'd expect scenario one and two to throw compiler and/or intellisense errors as one of the values does not exist on the type. However, after testing we found only scenario one throws errors whilst scenario two resolves without issue.

This is likely an understanding issue but from everything I've read (e.g. Template Literal Types we should be getting errors when a provided value doesn't exist.

Based on the above, is anyone able to explain why we only see errors on scenario one but not the scenario two?

Scenario One

Example Code

export type FileType = ".png" | ".tif" | ".tiff" | ".jpeg" | ".jpg";

const allowedFileTypes = [".exe"] as Array<FileType>;

Expectation: Compiler error as .exe doesn't exist

Outcome: Compiler error stating the value doesn't exist

Scenario Two

Example Code

export type FileType = ".png" | ".tif" | ".tiff" | ".jpeg" | ".jpg";

const allowedFileTypes = [".exe", ".jpeg"] as Array<FileType>;

Expectation: Compiler error as .exe doesn't exist

Outcome: No compiler errors

Scenario Three

Example Code

export type FileType = ".png" | ".tif" | ".tiff" | ".jpeg" | ".jpg";

const allowedFileTypes = [".png", ".jpeg"] as Array<FileType>;

Expectation: No compiler errors

Outcome: No compiler errors

CodePudding user response:

as Type is a way of saying "This value is this type, even if it doesn't look like it".

You're overriding normal type detection.

It's useful for things like:

const response = await fetch('/some/url');
const data = await response.json();
return data as Foo;

where you know what the shape of the data you are getting back from the HTTP request is, but the compiler has no way of telling that unless you use as to tell it explicitly.


It is dangerous since you can specify a type that doesn't match the value you actually have (as you've discovered).

I have a project underway where I'm using superstruct in order to test the shape of my data inside a typeguard function instead of trusting to as.


You need to specify what is allowed to be assigned to the variable instead:

const allowedFileTypes: Array<FileType> = [".exe", ".jpeg"];
  • Related