Typescript Type: Restrict input to specific characters (Brainfuck)

In my Typescript Brainfuck interpreter (or executer), I am looking to implement a validation process for the input. The goal is to create a type that only allows specific characters, similar to this:

type BrainfuckCode = /* Custom type that permits only <>+-.,[] */

const input1: BrainfuckCode = "+++++++>"
// No error should occur in this case

const input2: BrainfuckCode = "+++++++>INVALID CHARACTERS"
// An error should be triggered here

I'm trying to find a solution without hardcoding the string length. Here's what I have so far:

type BrainfuckCode = "<" | ">" | "+" | "-" | "." | "," | "[" | "]"

Answer №1

Template literal types allow you to ensure that a string:

  • consists of exactly one valid character, or
  • starts with a valid character and the rest of the string follows the pattern recursively.
type BFChar = "<" | ">" | "+" | "-" | "." | "," | "[" | "]"
type IsBF<T extends string> = T extends BFChar
    ? T
    : T extends `${BFChar}${infer R}`
        ? IsBF<R>
        : never;

const badCode = '<<foo';
type badIsValid = IsBF<typeof badCode>; // never

const goodCode = '<<';
type goodIsValid = IsBF<typeof goodCode>; // not never

Keep in mind that this validation method only applies to strings present within the source code, for example:

const theString = '...';

It won't work for dynamically generated strings (like those from user input) since they are typed as string and type verification is only available in pre-compiled code, not in the resulting JavaScript.

If you need to validate dynamically generated strings, you'll have to implement the validator using JavaScript.

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

Navigating to a specific attribute within a higher-level Component

Within my top-level Component, I have a property that is populated with data from an HTTP source. Here is how it is implemented in a file named app.ts: import {UserData} from './services/user-data/UserData'; Component({ selector: 'app& ...

Passing an array from a parent component to a child component in Angular

Just to give you some background, I only started my Angular learning journey about a week ago, so feel free to start from the very beginning. So, how can this be achieved? Inside app.component.ts, there is a standard array that needs to be accessible by m ...

Finding the root directory of a Node project when using a globally installed Node package

I've developed a tool that automatically generates source code files for projects in the current working directory. I want to install this tool globally using npm -g mypackage and store its configuration in a .config.json file within each project&apos ...

What is the best way to display just the selection outcome?

Currently, my code displays a full list of clinics. When I select a province in the dropdown menu, it only shows the clinics located in that specific province. I would like to modify this behavior so that the full list of clinics is not visible initially ...

The seamless union of Vuestic with Typescript

Seeking advice on integrating Typescript into a Vuestic project as a newcomer to Vue and Vuestic. How can I achieve this successfully? Successfully set up a new project using Vuestic CLI with the following commands: vuestic testproj npm install & ...

Exploring the narrowing capabilities of TypeScript within while loops

When I write while loops, there are times when I know for sure that a certain value exists (connection in this case), but the control flow analysis is unable to narrow it down. Here's an illustration: removeVertex(vertex: string) { const c ...

Tips on improving TypeScript code with dynamic variables for successful linting

Is there a proper way to refactor the creation of dynamic variables in TypeScript? I am encountering an error when trying to assign a value to obj.identifier which is not known. What would be the correct approach for refactoring this scenario? interface te ...

Guide on creating a zodiac validator that specifically handles properties with inferred types of number or undefined

There are some predefined definitions for an API (with types generated using protocol buffers). I prefer not to modify these. One of the types, which we'll refer to as SomeInterfaceOutOfMyControl, includes a property that is a union type of undefined ...

Guide to transforming an embed/nested FormGroup into FormData

Presenting my Form Group: this.storeGroup = this.fb.group({ _user: [''], name: ['', Validators.compose([Validators.required, Validators.maxLength(60)])], url_name: [''], desc: ['', Validators.compose([Valida ...

Errors encountered when using Input onChange with React and TypeScript: jsx no-lambda and no-bind issues

While creating a demonstration for a simple task, I encountered some challenges with the taskNameInput component. Despite my attempts, I kept encountering errors. How can I resolve these issues in React when using Typescript? You can refer to my GitHub re ...

Exploring the functionality of className using materialUI

Attempting to test whether my component has a specific class is proving challenging. This difficulty stems from the fact that the class is generated using MaterialUI. For instance, I am looking for a class named spinningIconCenter, but in reality, it appea ...

Avoid the auto-generated modifications in valueChanges for FormControl

Currently, I have a registration form for events where users are required to input the date, time, and recurrence frequency (daily, weekly, monthly, or none). Additionally, there is an option for users to specify when they want the recurrence to end. Howev ...

Is utilizing the service through the bootstrap application providers equivalent to specifying providedIn: root when declaring the service?

Let's consider a scenario where we have a service named SomeService that is defined within a library without the providedIn: root injectable metadata configuration. @Injectable() export class SomeService { ...} Now, in our application, we include Som ...

Exploring the Possibilities with Material UI v4: Expanding on PaletteColor

Looking to make a simple adjustment in Material UI v4's (v4.11) palette, specifically adding a new field to PaletteColorOptions like darker?: string. The type definition can be found in the relevant Material UI module: createPalette.d.ts export type ...

Tips for generating a subprocess with exec within a TypeScript Class

I am looking to automate the process of creating MRs in GitLab. When a button is clicked in my React/Typescript UI, I want to trigger command-line code execution within my Typescript class to clone a repository. However, every time I attempt to use exec, I ...

Determine the generic parameter of the output type by analyzing the resolved value of a data type within the function

I am looking to automatically determine the generic parameter of the return type by utilizing the resolved value of a type within the function. Consider the following: export type Context = any; export type Handler<T> = (ctx: Context) => Promise& ...

Beneath the Surface: Exploring Visual Studio with NPM and Typescript

Can you explain how Visual Studio (2015) interacts with external tools such as NPM and the Typescript compiler (tsc.exe)? I imagine that during the building of a solution or project, MSBuild is prompted to execute these additional tools. I'm curious a ...

Chai.request does not exist as a method

I'm encountering an issue with the code below: import app from '../src/app'; import * as chai from 'chai'; import chaiHttp = require('chai-http'); chai.use(chaiHttp); const expect = chai.expect; describe('Get /&ap ...

What could be causing the issue with Vite build and npm serve not functioning together?

After shifting from CRA to VITE, I am encountering a problem with serving my app. I successfully build my app using vite build. and can serve it using Vite serve without any issues. However, I want to use npm's serve command. Whenever I run vite bui ...

What purpose does the pipe method serve in RxJS?

It seems like I understand the basic concept, but there are a few unclear aspects. Here is my typical usage pattern with an Observable: observable.subscribe(x => { }) If I need to filter data, I can achieve this by: import { first, last, map, reduce, ...