typescript_scribe
v0.3.5
Published
A lightweight library to infer JavaScript object structures at runtime and generate TypeScript types, helping developers ensure type safety and reduce manual type definitions.
Downloads
50
Maintainers
Readme
typescript_scribe
Table of Contents
- Introduction
- Features
- Prerequisites
- Installation
- Basic Usage
- Real-World Examples
- Advanced Usage
- TypeScript Types
- Handling Edge Cases
- Additional Notes
- Known Issues and Limitations
- Contributing
- License
Introduction
typescript_scribe
is a lightweight library that automatically infers the structure of JavaScript objects and generates corresponding TypeScript types. It helps engineers quickly generate type definitions from dynamic data, reducing manual work and improving code quality.
Features
- Type Inference for Objects and Arrays: Automatically infers types from complex and nested objects or arrays.
- Date and Promise Handling: Correctly infers
Date
andPromise
objects in JavaScript. - Mixed Types and Empty Arrays: Handles arrays with mixed types, returning
'mixed'
for accurate representation, and infers empty arrays as['unknown']
. - Support for Nested Object Structures: Recursively infers types for deeply nested objects and arrays with ease.
- TypeScript-First Approach: Generates TypeScript-compatible type definitions without the need for manual intervention.
Prerequisites
- Node.js: Ensure you have Node.js installed (version 16.x or above recommended).
- npm: Ensure npm is installed. It comes bundled with Node.js.
- TypeScript: You should have TypeScript installed and set up in your project.
Installation
npm install typescript_scribe
or yarn add typescript_scribe
Basic Usage
Infer Type
Use the inferType
function to deduce the structure of your JavaScript object.
import { inferType } from 'typescript_scribe';
const myObj = {
id: 1,
name: "Anthony",
time: new Date(),
tasks: ["code", "sleep", "repeat"]
};
// Infer the structure of the object
const inferred = inferType(myObj);
console.log(inferred);
// Output:
{
id: 'number',
name: 'string',
time: 'Date',
tasks: ['string']
}
Generate TypeScript Type
Use generateTypeScriptType
to generate a TypeScript type definition based on the inferred structure.
import { generateTypeScriptType } from 'typescript_scribe';
const myObj = { id: 1, name: "Anthony", tasks: ["code", "sleep", "repeat"] };
// Generate a TypeScript type from the object
const tsType = generateTypeScriptType(myObj);
console.log(tsType);
// Output:
type GeneratedType = {
id: number;
name: string;
tasks: string[];
};
Real-World Examples
Handling a Complex API Response
When working with dynamic API responses, typescript_scribe
can infer complex nested structures, saving you time on manual type definition.
const apiResponse = {
user: {
id: 1,
name: "John Doe",
address: {
city: "New York",
postalCode: 10001,
},
tags: ["admin", "contributor"],
settings: {
newsletter: true,
timezone: "EST",
},
},
};
// Infer the structure of the response
const inferredApiResponse = inferType(apiResponse);
console.log(inferredApiResponse);
// Output:
{
user: {
id: 'number',
name: 'string',
address: {
city: 'string',
postalCode: 'number',
},
tags: ['string'],
settings: {
newsletter: 'boolean',
timezone: 'string',
}
}
}
Inferring Types for Dynamic Form Data
Working with dynamic forms? Let typescript_scribe infer the structure of the collected data for you.
const formData = {
name: "Jane Doe",
age: 29,
preferences: {
theme: "dark",
notifications: true,
},
items: [
{ id: 1, name: "Item 1", price: 9.99 },
{ id: 2, name: "Item 2", price: 19.99 },
],
};
// Generate the TypeScript type from the dynamic form data
const tsFormDataType = generateTypeScriptType(formData, "FormData");
console.log(tsFormDataType);
// Output:
type FormData = {
name: string;
age: number;
preferences: {
theme: string;
notifications: boolean;
};
items: {
id: number;
name: string;
price: number;
}[];
};
Advanced Usage
Custom Type Names
You can customize the name of the generated TypeScript type by passing a second argument to generateTypeScriptType
.
const myObj = { id: 1, name: "Anthony", tasks: ["code", "sleep", "repeat"] };
const tsType = generateTypeScriptType(myObj, 'CustomType');
console.log(tsType);
// Output:
type CustomType = {
id: number;
name: string;
tasks: string[];
};
Nested Object Structures
typescript_scribe
can infer nested objects and arrays, handling complex structures seamlessly.
const complexObj = {
id: 1,
profile: {
name: "Anthony",
details: {
age: 35,
skills: ["TypeScript", "JavaScript", "AWS"]
}
}
};
const inferredComplex = inferType(complexObj);
console.log(inferredComplex);
// Output:
{
id: 'number',
profile: {
name: 'string',
details: {
age: 'number',
skills: ['string']
}
}
}
const tsComplexType = generateTypeScriptType(complexObj, 'ComplexType');
console.log(tsComplexType);
// Output:
type ComplexType = {
id: number;
profile: {
name: string;
details: {
age: number;
skills: string[];
};
};
};
TypeScript Types
The InferredType
returned by inferType
can be one of the following:
'string'
,'number'
,'boolean'
for primitives.'Date'
forDate
objects.'Promise'
for Promise objects.'null'
,'undefined'
for null and undefined values.'mixed'
for arrays with mixed types.['unknown']
for empty arrays.- A nested type structure for objects.
Handling Edge Cases
- Arrays with Mixed Types: If an array contains elements of different types (e.g.,
[1, 'a', true]
), the inferred type will be['mixed']
. - Empty Objects and Arrays: Empty objects will return
{}
, and empty arrays will return['unknown']
. - Functions: Functions are not supported and will throw an error if passed into
inferType
. - Circular References: Circular references are not supported and may cause the function to throw an error or behave unexpectedly.
Additional Notes
- Date Handling:
Date
objects are inferred as'Date'
to ensure accurate type inference, reflecting their use as a specialized type in TypeScript. - Empty Arrays: Empty arrays are inferred as
['unknown']
, representing an array with unknown element types. - Function Error: If a function is passed to
inferType
, an error will be thrown because functions are not supported for type inference.
Known Issues and Limitations
- Currently, circular references are not handled.
- Very large objects with deep nesting might impact performance.
- Certain JavaScript-specific objects (e.g.,
Map
,Set
) are not yet supported for type inference.
Contributing
Support the project
If you find this library helpful and want to support its development, consider buying me a coffee ☕. Your support fuels my ability to keep building great tools for the community!
How to contribute
- Fork the repository.
- Create a new branch (
git checkout -b feature-branch
). - Make your changes and commit them (
git commit -m 'Add some feature'
). - Push to the branch (
git push origin feature-branch
). - Open a pull request.
For large changes, open an issue first to discuss the potential implementation.
Pipeline
We are currently implementing a GitHub Actions pipeline (work in progress) to automate the testing, linting, and publishing process for the project. This will ensure:
- Every pull request is automatically tested using Vitest.
- Linting is enforced with XO to maintain code quality.
- Successful changes are packaged and prepared for npm publishing.
Future Pipeline Improvements
- Cross-environment compatibility testing.
Linting with XO
We use XO as our linter because it enforces best practices and works seamlessly with TypeScript and JavaScript projects.
To run the linter:
npm run lint
For more details, check out the official XO documentation.
Testing with Vitest
We use Vitest as the test framework because it's modern, fast, and supports both TypeScript and ES Modules seamlessly.
To run the tests:
npm run test
For more details, check out the official Vitest documentation.
License
This project is licensed under the MIT License.