Secure mustache templates for data validation

Is there a method to achieve the following?:

my-custom-template.mstach

Hello {{name}}!

script.js

import { readFileSync, writeFileSync } from 'fs';
import * as Mustache from 'mustache';

export interface Person {
    name: string;
}

const data: Person = {
    name: 'Jon'
};

const templateContent = readFileSync('my-custom-template.mustache', 'utf-8');

// finding a way to specify the type of data in IDE
const result = Mustache.render(templateContent, data);

writeFileSync('my-custom-template.html', result, 'utf-8');

In case you were to modify it like this:

my-custom-template.mstach

Hello {{name}}, {{age}} <!-- red squiggles under age -->

This would result in having age not being part of the type Person, causing red squiggles. Seeking a solution that is compatible with Visual Studio Code.

Update:
Just to clarify, I am aiming for the outcome:

Hello {{name}}, {{age}} <!-- red squiggles under age -->
, rather than facing an issue with it.

Answer №1

Finding a simple solution may be difficult, but there are complex methods available. One idea that comes to mind is creating a tool to convert your *.mustache templates into typescript modules. By importing these modules like regular typescript files instead of using fs.readFileSync, you can simplify the process. Here's an example of how the compiled template with age might appear:

import * as Mustache from 'mustache';

const template = 'Hello {{name}}, {{age}} <!-- red squiggles under age -->';
export interface TemplateParams {
    name: string;
    age: string;
}
export default function render(params: TemplateParams): string {
    return Mustache.render(template, params);
}

This tool will need to be integrated into your build scripts for your app and set up to build incrementally in watch mode.

Answer №2

According to Nikita's explanation, there are no existing tools to achieve this using Mustache, so you would have to create a compiler yourself. If you're open to exploring alternatives to Mustache, consider using template literals instead.

I developed a tool called embedded-typescript that leverages a compiler to produce type-safe templates with a syntax inspired by ejs. This project is open source, so you can use it as a foundation for creating something similar tailored to a Mustache-like syntax.

Answer №3

Instead of using an interface, one alternative is to declare a type for your objects in JavaScript. This type declaration works similarly to Traits and allows you to define new properties for any JS Object. However, it will throw an error if you attempt to use the wrong type for a specific property.

import { readFileSync, writeFileSync } from 'fs';
import * as Mustache from 'mustache';

export interface PersonWithName {
    name: string;
}

export declare type Person = PersonWithName | any;

const hash: Person = {
    name: 'Jon'
};

const hashWithAge: Person = {
    name: 'Jon',
    age: 10,
    newAge: 20
};

const template = readFileSync('my-template.mustache', 'utf-8');

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 cancel function in lodash's debounce feature does not successfully halt the execution of the

In my angular application, I have implemented http calls on each modelChange event with the help of lodash's _.debounce(). However, I'm facing an issue where I am unable to cancel these calls after the initial successful execution of debounce. ...

Verify the presence of identical items in the array

I have been attempting to identify any duplicate values within an array of objects and create a function in ES6 that will return true if duplicates are found. arrayOne = [{ agrregatedVal: "count", value: "Employee Full Name" }, { agrrega ...

Terminal displays Typescript variable syntax error

Recently, I've been delving into TypeScript using Visual Studio Code. However, I've encountered a perplexing syntax error that stems from how I've defined a variable. Here's an example of my declaration: let year:number = 2015 My term ...

Automatically adjust padding in nested lists with ReactJS and MaterialUI v1

How can I automatically add padding to nested lists that may vary in depth due to recursion? Currently, my output looks like this: https://i.stack.imgur.com/6anY9.png: However, I would like it to look like this instead: https://i.stack.imgur.com/dgSPB. ...

Utilize the v-for Directive in Vue-Tables-2 Templates

I am looking to showcase the data fetched using axios in my dynamically keyed datatables by creating a template. Data Set : "environment": "production", "version": "5.6", "apache_version": "3.2.1" ...

When a 404 error is thrown in the route handlers of a Next.js app, it fails to display the corresponding 404 page

I am encountering an issue with my route handler in Next.js: export async function GET(_: Request, { params: { statusId } }: Params) { const tweetResponse = await queryClient< Tweet & Pick<User, "name" | "userImage" | &q ...

Interpret information in Angular 2 using Typescript

Just starting with Angular (IONIC) and need help. How can I extract the userId or id from this code? his.response = data. //Looking for guidance on accessing Json keys Response : { "userId": 1, "id": 1, "title": "sunt aut facere repellat providen ...

Understanding the functionality of imports within modules imported into Angular

I have been scouring through the documentation trying to understand the functionality of the import statement in JavaScript, specifically within the Angular framework. While I grasp the basic concept that it imports modules from other files containing expo ...

Leveraging Angular 4-5's HttpClient for precise typing in HTTP requests

Utilizing a helper service to simplify httpClient calls, I am eager to enforce strong typing on the Observable being returned. In my service where I utilize the api Service and attempt to obtain a strongly typed observable that emits: export class ApiU ...

What are the steps to resolve the issue of assigning void type to type ((event: MouseEvent<HTMLDivElement, MouseEvent>) => void) | undefined in a react application?

I'm trying to update the state isOpen to true or false when clicking on a div element, but I keep getting an error with the following code: function Parent() { const [isOpen, setIsOpen] = React.useState(false); return ( <Wrapper> ...

Can callback argument types be contingent on certain conditions? For example, could argument 0 be null if argument 1 is a string?

I am attempting to implement conditional type logic for the parameter types of a callback function. In this scenario, the first argument represents the value while the second argument could be an error message. type CallbackWithoutError = (value: string, ...

Make sure the static variable is set up prior to injecting the provider

In our Angular6 application, we utilize a globalcontextServiceFactory to initialize the application before rendering views. This process involves subscribing to get configuration from a back-end endpoint and then using forkJoin to retrieve environment app ...

Encountering errors with React Bootstrap during the build process

Currently, I am working on a Nextjs project integrating React bootstrap. Everything was functioning smoothly until today when all of the React bootstrap components started throwing the same error, leading to build failures. The 'Dropdown.Item' co ...

Populate a chart in real-time with data pulled directly from the Component

I'm completely new to Angular and I feel like I might be overlooking something important. Within my component, I have 3 variables which are populated after invoking the .subscribe method on an observable object. For example: this.interRetard = this ...

Collaborating on a project that has been developed using various editions of Typescript

Currently, I am part of a team working on a large project using Typescript in Visual Studio. As we have progressed through different versions of the project, we have encountered an issue with versioning the installed TypeScript within Visual Studio. Situa ...

What's the best way to include various type dependencies in a TypeScript project?

Is there a more efficient way to add types for all dependencies in my project without having to do it manually for each one? Perhaps there is a tool or binary I can use to install all types at once based on the dependencies listed in package.json file. I ...

Having trouble retrieving cookie in route.ts with NextJS

Recently, I encountered an issue while using the NextJS App Router. When attempting to retrieve the token from cookies in my api route, it seems to return nothing. /app/api/profile/route.ts import { NextResponse } from "next/server"; import { co ...

Encountering an error in Angular 8 with the plugin: Unhandled ReferenceError for SystemJS

I recently followed a tutorial on integrating plugins into my Angular application at this link. I'm trying to create a component in my Angular app that can execute and display an external component. However, I encountered the following error: Uncaugh ...

Exploring the Magic of Class Variable Destructuring in React

Is there a simpler method to break down a prop object and assign them to variables of the same name in the class? I am familiar with ({ first: this.first, second: this.second, } = props) however, it can get complicated when dealing with numerous variable ...

Guide to customizing CSS styles within a div element using TypeScript code in a Leaflet legend

I'm struggling to add a legend to my map using Angular 5 and typescript. I need help with setting CSS styles for the values (grades) that are displayed on the legend. Can someone guide me on where to put the styles? TS: createLegend() { let lege ...