Setting character limits when defining string variables in TypeScript

Upon reviewing the documentation, it appears that there is no straightforward method to perform type checking for the minimum and maximum length of a string data type.

However, is there a possible way to define a string data type using custom types in order to verify if the string's length falls within specified limits?

Answer №1

If you want to enforce a specific type in TypeScript, you can utilize a type constructor along with what is known as a "Phantom Type" (learn more about this concept in this interesting article). This technique ensures that a type cannot be directly assigned to a value.

For instance, consider the StringOfLength<Min,Max> type created using these methods:

type StringOfLength<Min, Max> = string & {
  min: Min;
  max: Max;
  StringOfLength: unique symbol // acting as the phantom type
};

// The following function acts as a type guard and confirms that a given string meets the criteria of being of type StringOfLength<Min,Max>
const isStringOfLength = <Min extends number, Max extends number>(
  str: string,
  min: Min,
  max: Max
): str is StringOfLength<Min, Max> => str.length >= min && str.length <= max;
    
// Define the type constructor function
export const stringOfLength = <Min extends number, Max extends number>(
  input: unknown,
  min: Min,
  max: Max
): StringOfLength<Min, Max> => {
  if (typeof input !== "string") {
    throw new Error("invalid input");
  }
    
  if (!isStringOfLength(input, min, max)) {
    throw new Error("input is not between specified min and max");
  }
    
  return input; // the type of input now becomes StringOfLength<Min,Max>
};

// Utilize the type constructor function
const myString = stringOfLength('hello', 1, 10) // myString will have type StringOfLength<1,10>

// The type constructor function fails when the input is invalid
stringOfLength('a', 5, 10) // Error: input is not between specified min and max

// Manually assigning StringOfLength is prevented by the use of the phantom type:
const a: StringOfLength<0, 10> = 'hello' // Type '"hello"' is not assignable to type { StringOfLength: unique symbol }

It's important to note that there are limitations to this approach - for example, it does not prevent the creation of an invalid type like StringOfLength<-1, -300>. However, runtime checks can be added within the stringOfLength constructor function to ensure that the min and max values passed are valid.

Note: In Typescript, this technique has become more commonly referred to as "branded types."

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The application within the Main Module is not being acknowledged by the other components within the module

I am facing an issue with my AngularJS application where the directive I created within the 'FormTest' module is not recognizing the variable 'app' even though it is defined within the same module. The error message I receive is TS2304 ...

At what point do we employ providers within Angular 2?

In the Angular 2 documentation, they provide examples that also use HTTP for communication. import { HTTP_PROVIDERS } from '@angular/http'; import { HeroService } from './hero.service'; @Component({ selector: 'my-toh&ap ...

Implement Material UI TextField to ensure all required fields are properly formatted

Looking to customize the underline border color of TextFields marked as mandatory within a form using react-hooks-form. I understand that I need to define a style for these fields, but I'm struggling with where to start... This is the current code s ...

Is a Javascript-only application compatible with Amazon S3 cloud storage?

I am currently investigating the validity of the following statement: Based on my research, it seems unlikely to create a web application using only JavaScript - without any server-side logic - hosted on Amazon S3 that can also store data solely on S3 whi ...

How can we merge all the values of keys within an object into a new array using ES6?

My objective is to transform dynamic data into an array based on the keys of the toolset object, which does not have a constant number of keys. { toolset:{ info1:{ event-date:{}, event-time:{}, }, info ...

What is the best way to extract a specific number from a table with Selenium, especially when the location remains consistent across all zip

Context: I am attempting to scrape data from a website with JavaScript using Selenium in Python. Goal: Extract a specific number from the table located at 159x26. I believed that this code would retrieve the number from row 159, column 26. Here is the c ...

Guide on accessing js file in an Angular application

I have a component where I need to create a function that can search for a specific string value in the provided JavaScript file. How can I achieve this? The file path is '../../../assets/beacons.js' (relative to my component) and it's named ...

Why is it displaying undefined even though there is data stored in Firebase?

I am experiencing an issue where the datatable row is displaying "undefined" instead of the data from my Firebase database. Even when I tried inserting random data into the HTML file for the datatable, it still shows undefined. Here is a link to My Datata ...

Using ngFor to display a default image

My latest project involved creating a table that displays various products along with their corresponding images. Everything was working smoothly until I encountered an issue. In instances where a product is created without an associated image, I decided ...

What could be the issue with my code? (Threejs spotlight shadow)

I recently created a Three.js scene featuring two cubes on a plane. The spotLight I placed in the top-left corner is intended to look at the coordinates 50, 0, -50. However, I noticed that the shadows appear odd and the light does not seem to be focusing ...

Sharing details of html elements using ng-click (AngularJS)

I am currently exploring options to enable users to click on a "open in new tab" link, which would essentially transfer that HTML element into a fresh window for their convenience. I am seeking advice on how to achieve this. At the moment, I am able to la ...

Top method for changing Enum to Set in TypeScript

Take a look at the enum below: enum Animes { OnePiece = 'One Piece', Naruto = 'Naruto', Bleach = 'Bleach' } How can we efficiently transform this enum into a Set? ...

Issue with Ajax communication to PHP script causing data not to be sent

I am developing a web application that functions as an extensive form which will later be converted into a PDF document. Upon submission of the form, all input data is sent to a PHP file where they are stored as variables to be included in the PDF. Some of ...

How to define a TypeScript recursive object with a defined endpoint?

Welcome to my first question! I am currently facing an issue with defining an object to store strings in multiple languages. I am looking for a flexible solution and have considered using a nested object structure. However, I want the final object to adhe ...

Is there a way to potentially utilize window.open() to open a specific section of a webpage?

My HTML page consists of 2 div blocks and 2 links. I want to open the content of the first div in a new window when the first link is clicked, and the content of the second div in another new window when the second link is clicked. You can find the code h ...

Latest Information Regarding Mongodb Aggregate Operations

Struggling to toggle a boolean value within an object that is part of a subdocument in an array. Finding it difficult to update a specific object within the array. Document: "_id" : ObjectId("54afaabd88694dc019d3b628") "Invitation" : [ { "__ ...

How is it that I can assign a string value to my declared number object parameter in Typescript?

In my code, I have defined an interface called DateArray: export interface DateArray { year : number; } Within my component, I am declaring a new variable named dateArray like this: private dateArray: DateArray = { year: null }; Then, I am a ...

Exploring the functionality of Typescript classes in a namespace through Jest testing

Within a certain namespace, I have created a method like so: // main.ts namespace testControl { export const isInternalLink = (link: string) => { return true; } } I also have a jest spec as shown below: // main.spec.ts test('sh ...

The issue with the Angular custom checkbox directive arises when using it within an ng-repeat

A personalized directive has been developed for checkboxes that is applicable throughout the application. The code for creating the checkbox is as follows: JS angular.module("myApp") .component("ngCheckbox", { template: '<di ...

Filtering Quantity Based on Specific Attribute in ReactJs

I want to implement a quantity filter that can be based on color, size, or both. For instance, when I select the red color, it should display the total quantity of red items available. However, if I choose both the color red and size small, it should show ...