Skip to content

Interpolation

The interpolation system replaces {{variable}} placeholders with actual values.

Simple one-shot interpolation.

import { interpolate } from '@t-req/core';
const result = interpolate('Hello {{name}}!', { name: 'World' });
// "Hello World!"
ParameterTypeDescription
templatestringString containing {{variable}} placeholders
variablesRecord<string, unknown>Variable values

string - The interpolated string.

Create a reusable interpolator with custom resolvers.

import { createInterpolator } from '@t-req/core';
const interp = createInterpolator({
resolvers: {
$env: (key) => process.env[key] || '',
$timestamp: () => String(Date.now()),
$uuid: () => crypto.randomUUID(),
},
});
const result = await interp.interpolate(
'Time: {{$timestamp()}} ID: {{$uuid()}}',
{}
);
OptionTypeDefaultDescription
resolversRecord<string, Resolver>{}Custom resolver functions
undefinedBehavior'throw' | 'keep' | 'empty''throw'How to handle undefined variables

Controls what happens when a variable is not found:

  • 'throw' — Throw an error (default, recommended for catching typos)
  • 'keep' — Keep the {{variable}} placeholder unchanged
  • 'empty' — Replace with an empty string
const interp = createInterpolator({
undefinedBehavior: 'keep', // {{missing}} stays as "{{missing}}"
});

Interpolate a string template.

const result = await interp.interpolate(
'GET {{baseUrl}}/users/{{userId}}',
{ baseUrl: 'https://api.example.com', userId: '123' }
);
// "GET https://api.example.com/users/123"
{{variableName}}
interpolate('Hello {{name}}', { name: 'World' });
// "Hello World"
{{object.property}}
{{object.nested.value}}
interpolate('User: {{user.name}}', {
user: { name: 'John', id: 123 }
});
// "User: John"
{{$resolverName()}}
{{$resolverName(arg1)}}
{{$resolverName(arg1, arg2)}}
const interp = createInterpolator({
resolvers: {
$random: (min = '0', max = '100') => {
const minNum = Number(min);
const maxNum = Number(max);
return String(Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
},
},
});
await interp.interpolate('Value: {{$random(1, 10)}}', {});
// "Value: 7" (random between 1-10)
type Resolver = (...args: string[]) => string | Promise<string>;

Resolvers:

  • Receive string arguments (parsed from the template)
  • Return a string (sync) or Promise (async)
  • Are called with $ prefix in templates
$env: (key) => process.env[key] || ''
Authorization: Bearer {{$env(API_TOKEN)}}
$timestamp: () => String(Date.now()),
$isoDate: () => new Date().toISOString(),
$date: (format = 'YYYY-MM-DD') => {
// Implement date formatting
return new Date().toISOString().split('T')[0];
},
$uuid: () => crypto.randomUUID(),
$random: (min = '0', max = '100') => {
return String(Math.floor(Math.random() * (Number(max) - Number(min) + 1)) + Number(min));
},
$randomString: (length = '8') => {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < Number(length); i++) {
result += chars[Math.floor(Math.random() * chars.length)];
}
return result;
},
$base64: (value) => Buffer.from(value).toString('base64'),
$urlEncode: (value) => encodeURIComponent(value),
$jsonStringify: (value) => JSON.stringify(value),
$fetchSecret: async (key) => {
const response = await fetch(`https://vault.example.com/secrets/${key}`);
const { value } = await response.json();
return value;
},

Interpolate all string values in an object:

const request = {
url: 'https://{{baseUrl}}/users/{{userId}}',
headers: {
Authorization: 'Bearer {{token}}',
},
};
// Recursively interpolate
function interpolateObject(obj, variables) {
if (typeof obj === 'string') {
return interpolate(obj, variables);
}
if (Array.isArray(obj)) {
return obj.map(item => interpolateObject(item, variables));
}
if (typeof obj === 'object' && obj !== null) {
const result = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = interpolateObject(value, variables);
}
return result;
}
return obj;
}
import type {
Interpolator,
InterpolateOptions,
Resolver,
} from '@t-req/core';