{"id":22896227,"url":"https://github.com/loderunner/typelit","last_synced_at":"2026-02-23T20:40:57.895Z","repository":{"id":265942139,"uuid":"896891212","full_name":"loderunner/typelit","owner":"loderunner","description":"A type-safe string templating library for TypeScript","archived":false,"fork":false,"pushed_at":"2025-03-03T01:48:53.000Z","size":338,"stargazers_count":1,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T02:05:05.267Z","etag":null,"topics":["interpolation","string-formatting","string-interpolation","string-manipulation","string-templates","strongly-typed","template","templating","text-processing","type-checking","type-inference","type-safe","typescript","zero-dependencies","zero-runtime"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/loderunner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-01T15:03:02.000Z","updated_at":"2025-04-01T08:48:16.000Z","dependencies_parsed_at":"2024-12-03T10:05:48.267Z","dependency_job_id":null,"html_url":"https://github.com/loderunner/typelit","commit_stats":null,"previous_names":["loderunner/prmpt","loderunner/typelit"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loderunner%2Ftypelit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loderunner%2Ftypelit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loderunner%2Ftypelit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loderunner%2Ftypelit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loderunner","download_url":"https://codeload.github.com/loderunner/typelit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248991544,"owners_count":21194894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interpolation","string-formatting","string-interpolation","string-manipulation","string-templates","strongly-typed","template","templating","text-processing","type-checking","type-inference","type-safe","typescript","zero-dependencies","zero-runtime"],"created_at":"2024-12-13T23:34:03.994Z","updated_at":"2026-02-23T20:40:57.889Z","avatar_url":"https://github.com/loderunner.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Typelit\n\n\u003e \"Type-safe template string literals\"\n\n[![NPM Version](https://img.shields.io/npm/v/typelit?logo=npm)](https://www.npmjs.com/package/typelit)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/typelit) ](https://bundlephobia.com/package/typelit)\n[![dependency count](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fbundlephobia.com%2Fapi%2Fsize%3Fpackage%3Dtypelit\u0026query=dependencyCount\u0026label=dependencies)](https://bundlephobia.com/package/typelit)\n[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/loderunner/typelit/lint-test-build.yml?logo=github)](https://github.com/loderunner/typelit/actions/workflows/lint-test-build.yml?query=branch%3Amain)\n[![GitHub License](https://img.shields.io/github/license/loderunner/typelit)](./LICENSE)\n\nA type-safe string templating library for TypeScript that provides\nstrongly-typed variable references with support for nested paths. Create\ntemplate strings with compile-time type checking and automatic context type\ninference.\n\nTypelit allows you to write template strings that are both type-safe and easy to\nread. Variables are referenced using a familiar template literal syntax while\nmaintaining full type information about the required context object structure.\n\n## Table of contents\n\n- [Getting Started](#getting-started)\n  - [Installation](#installation)\n  - [Basic Usage](#basic-usage)\n  - [Nested Context Objects](#nested-context-objects)\n- [Template Function](#template-function)\n  - [Features](#features)\n- [Variable Creators](#variable-creators)\n  - [String](#string)\n  - [Number](#number)\n  - [Boolean](#boolean)\n  - [BigInt](#bigint)\n  - [Date](#date)\n  - [JSON](#json)\n- [Custom Variable Creators](#custom-variable-creators)\n  - [Customizing String Conversion](#customizing-string-conversion)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Getting Started\n\n### Installation\n\nInstall using npm:\n\n```bash\nnpm install typelit\n```\n\nOr using yarn:\n\n```bash\nyarn add typelit\n```\n\nThe library is available in multiple module formats to support different\nenvironments:\n\n- CommonJS (Node.js):\n\n```typescript\nconst typelit = require('typelit');\nconst greeting = typelit`Hello ${typelit.string('name')}!`;\n```\n\n- ESM (Modern JavaScript):\n\n```typescript\nimport typelit from 'typelit';\nconst greeting = typelit`Hello ${typelit.string('name')}!`;\n```\n\n- UMD (Browser):\n\n```html\n\u003cscript src=\"https://unpkg.com/typelit\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  const greeting = typelit`Hello ${typelit.string('name')}!`;\n\u003c/script\u003e\n```\n\nEach format provides identical functionality - pick the one that best suits your\nenvironment. The library includes TypeScript type definitions that work\nautomatically with all formats.\n\n### Basic Usage\n\nFirst, import the library:\n\n```typescript\nimport typelit from 'typelit';\n```\n\nLet's start with a simple greeting template:\n\n```typescript\n// Create a simple template with one variable\nconst greeting = typelit`Hello ${typelit.string('name')}!`;\n\n// Use the template with a context object\nconst result = greeting({ name: 'Alice' }); // \"Hello Alice!\"\n```\n\n### Nested Context Objects\n\nYou can also create templates with nested variable paths:\n\n```typescript\n// Create a template with nested variables\nconst template = typelit`Hello ${typelit.string('user', 'name')}! You are ${typelit.number('user', 'age')} years old.`;\n\n// TypeScript knows exactly what shape the context object needs to have\nconst result = template({\n  user: {\n    name: 'Alice',\n    age: 30,\n  },\n}); // \"Hello Alice! You are 30 years old.\"\n\n// This would cause a type error:\ntemplate({\n  user: {\n    name: 'Bob',\n    // Error: missing required property 'age'\n  },\n});\n```\n\n## Template Function\n\nThe `typelit` tag function creates template functions that evaluate a string\ntemplate using values from a context object. The template function takes a\ncontext object as input and returns the evaluated string with all variables\nreplaced by their values.\n\nWhen creating a template, TypeScript infers the required shape of the context\nobject from the variables used in the template.\n\n```typescript\n// Example showing type inference\nconst welcome = typelit`Welcome back, ${typelit.string('username')}!`;\n\n// TypeScript infers that the context must have a 'username' property\nwelcome({ username: 'alice' }); // OK\nwelcome({ user: 'bob' }); // Type error: missing username\nwelcome({ username: 123 }); // Type error: number is not assignable to string\n```\n\n### Features\n\nThe `typelit` function serves a dual purpose:\n\n1. As a template tag function that creates typed template functions\n2. As a namespace that provides variable creators (`string`, `number`, etc.)\n\nTemplate functions created with `typelit` offer:\n\n- **Type Safety**: All variables are fully typed, ensuring you can't pass the\n  wrong type of value.\n- **Path Inference**: TypeScript automatically infers the required structure of\n  your context object.\n- **Composition**: Templates can be composed to build more complex strings:\n\n```typescript\nconst firstName = typelit`${typelit.string('user', 'firstName')}`;\nconst lastName = typelit`${typelit.string('user', 'lastName')}`;\nconst fullName = typelit`${firstName} ${lastName}`;\n\n// Both templates require the same context structure\nfirstName({ user: { firstName: 'John' } });\nfullName({ user: { firstName: 'John', lastName: 'Doe' } });\n```\n\n- **Compile-Time Validation**: TypeScript catches errors before runtime:\n  - Missing or misspelled variable paths\n  - Incorrect value types\n  - Missing context properties\n  - Invalid template syntax\n\n## Variable Creators\n\nTypelit provides built-in variable creators for common data types. These are\nused to define variables in your templates with type-safe paths.\n\n### String\n\nUse `typelit.string()` to create string variables in your templates:\n\n```typescript\n// Simple string variable\nconst greeting = typelit`Hello ${typelit.string('name')}!`;\ngreeting({ name: 'Alice' }); // \"Hello Alice!\"\n\n// Nested string variable\nconst userEmail = typelit`Contact: ${typelit.string('user', 'email')}`;\nuserEmail({ user: { email: 'alice@example.com' } }); // \"Contact: alice@example.com\"\n```\n\n### Number\n\nUse `typelit.number()` to create number variables:\n\n```typescript\n// Simple number variable\nconst age = typelit`Age: ${typelit.number('age')} years old`;\nage({ age: 25 }); // \"Age: 25 years old\"\n\n// Nested number variable\nconst score = typelit`Score: ${typelit.number('game', 'score')} points`;\nscore({ game: { score: 100 } }); // \"Score: 100 points\"\n```\n\n### Boolean\n\nUse `typelit.boolean()` to create boolean variables:\n\n```typescript\n// Simple boolean variable\nconst status = typelit`Status: ${typelit.boolean('isActive')}`;\nstatus({ isActive: true }); // \"Status: true\"\n\n// Nested boolean variable\nconst accountStatus = typelit`Account active: ${typelit.boolean('user', 'account', 'enabled')}`;\naccountStatus({ user: { account: { enabled: false } } }); // \"Account active: false\"\n```\n\n### BigInt\n\nUse `typelit.bigint()` to create bigint variables:\n\n```typescript\n// Simple bigint variable\nconst id = typelit`ID: ${typelit.bigint('userId')}`;\nid({ userId: 9007199254740991n }); // \"ID: 9007199254740991\"\n\n// Nested bigint variable\nconst transactionId = typelit`Transaction: ${typelit.bigint('payment', 'transactionId')}`;\ntransactionId({ payment: { transactionId: 123456789n } }); // \"Transaction: 123456789\"\n```\n\n### Date\n\nUse `typelit.date()` to create Date variables that automatically convert\nJavaScript Date objects to strings:\n\n```typescript\n// Simple date variable\nconst eventDate = typelit`Event date: ${typelit.date('date')}`;\neventDate({ date: new Date('2024-12-25') }); // \"Event date: Wed Dec 25 2024 00:00:00 GMT+0000\"\n\n// Nested date variable\nconst appointmentTime = typelit`Appointment scheduled for: ${typelit.date('calendar', 'appointment')}`;\nappointmentTime({\n  calendar: { appointment: new Date('2024-12-25T15:30:00Z') },\n}); // \"Appointment scheduled for: Wed Dec 25 2024 15:30:00 GMT+0000\"\n```\n\n### JSON\n\nUse `typelit.json()` to create variables that automatically stringify any value\nto JSON with proper formatting:\n\n```typescript\n// Simple JSON variable\nconst data = typelit`Data: ${typelit.json('config')}`;\ndata({ config: { enabled: true, count: 42 } });\n// \"Data: {\n//   \"enabled\": true,\n//   \"count\": 42\n// }\"\n\n// Nested JSON variable\nconst userProfile = typelit`Profile: ${typelit.json('user', 'profile')}`;\nuserProfile({\n  user: {\n    profile: {\n      name: 'Alice',\n      preferences: {\n        theme: 'dark',\n        notifications: true,\n      },\n    },\n  },\n});\n// \"Profile: {\n//   \"name\": \"Alice\",\n//   \"preferences\": {\n//     \"theme\": \"dark\",\n//     \"notifications\": true\n//   }\n// }\"\n```\n\n## Custom Variable Creators\n\nYou can create your own variable creators for any type using the `createType`\nfunction. Here's a basic example creating a variable creator for JavaScript's\n`Date` type:\n\n```typescript\nimport { createType } from 'typelit';\n\n// Create a variable creator for Date\nconst typelitDate = createType\u003cDate\u003e();\n\n// Use it in a template\nconst template = typelit`Event starts at ${typelitDate('event', 'startTime')}`;\n\n// The context object requires a Date instance\nconst result = template({\n  event: {\n    startTime: new Date('2024-12-25T10:00:00Z'),\n  },\n}); // \"Event starts at Wed Dec 25 2024 10:00:00 GMT+0000\"\n\n// Type error: string is not assignable to Date\ntemplate({\n  event: {\n    startTime: '2024-12-25', // Error!\n  },\n});\n```\n\nLike built-in variable creators, custom ones:\n\n- Support nested paths\n- Provide full type inference for the context object\n- Enforce the correct type at compile time\n\n### Customizing String Conversion\n\nThe `createType` function accepts an optional `options`. The `options.stringify`\nparameter is a function that takes a value of your type and returns a string.\n\nHere are some examples of customizing string conversion:\n\n```typescript\n// Custom date formatting\nconst typelitDate = createType\u003cDate\u003e({\n  stringify: (date) =\u003e\n    date.toLocaleDateString('en-US', {\n      weekday: 'short',\n      month: 'short',\n      day: 'numeric',\n      year: 'numeric',\n    }),\n});\n\nconst event = typelit`Event: ${typelitDate('date')}`;\nevent({ date: new Date('2024-12-25') }); // \"Event: Wed, Dec 25, 2024\"\n\n// Currency formatting\nconst typelitPrice = createType\u003cnumber\u003e({\n  stringify: (price) =\u003e\n    new Intl.NumberFormat('en-US', {\n      style: 'currency',\n      currency: 'USD',\n    }).format(price),\n});\n\nconst price = typelit`Total: ${typelitPrice('amount')}`;\nprice({ amount: 42.99 }); // \"Total: $42.99\"\n\n// Custom object formatting\ntype User = { id: number; name: string };\nconst typelitUser = createType\u003cUser\u003e({\n  stringify: (user) =\u003e `#${user.id} ${user.name}`,\n});\n\nconst user = typelit`Created by: ${typelitUser('author')}`;\nuser({ author: { id: 123, name: 'Alice' } }); // \"Created by: #123 Alice\"\n```\n\nWithout a custom `stringify` function, `createType` uses JavaScript's built-in\n`String()` function to convert values to strings. This is equivalent to:\n\n```typescript\ncreateType\u003cT\u003e({ stringify: String });\n```\n\nYou might want to provide a custom `stringify` function when:\n\n- Formatting dates in a specific way\n- Formatting numbers (currency, percentages, fixed decimal places)\n- Creating a custom string representation for objects\n- Adding prefixes, suffixes, or other decorations to values\n- Internationalizing or localizing output\n\nSee the [examples directory](./examples) for practical examples.\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md)\nfor details on how to set up the development environment and our contribution\nprocess.\n\n## License\n\nCopyright 2024 Charles Francoise\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the License for the\nspecific language governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floderunner%2Ftypelit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floderunner%2Ftypelit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floderunner%2Ftypelit/lists"}