{"id":10527,"library":"avro-typescript","title":"Avro TypeScript Generator","description":"avro-typescript is a dedicated library for generating TypeScript interfaces from Apache Avro schemas. It takes an Avro schema, typically provided as a JavaScript object parsed from JSON, and outputs the corresponding TypeScript code as a string. The library is currently at version 1.3.0 and appears to be actively maintained, with recent updates addressing issues like top-level enum support. It supports most standard Avro features, including enumerated types, maps, named records, unions, and primitives, along with mandatory and optional fields. A key differentiator is its ability to override logical Avro types (e.g., converting an Avro `int` with a `date` logical type to a TypeScript `Date` object) by passing a mapping in the options. This tool operates effectively in both Node.js and browser environments, focusing solely on type generation rather than schema parsing or serialization/deserialization, which often relies on companion libraries like `avsc`.","status":"active","version":"1.3.0","language":"javascript","source_language":"en","source_url":"https://github.com/joewood/avro-typescript","tags":["javascript","avro","typescript"],"install":[{"cmd":"npm install avro-typescript","lang":"bash","label":"npm"},{"cmd":"yarn add avro-typescript","lang":"bash","label":"yarn"},{"cmd":"pnpm add avro-typescript","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library primarily uses named ESM imports. While CommonJS `require` might work in some transpiled environments, native ESM import is the recommended approach for modern Node.js and bundlers.","wrong":"const avroToTypeScript = require('avro-typescript');","symbol":"avroToTypeScript","correct":"import { avroToTypeScript } from 'avro-typescript';"},{"note":"The `RecordType` interface is exported directly from the main package entry point, representing a standard Avro record schema structure for type safety when defining schemas programmatically.","wrong":"import { RecordType } from 'avro-typescript/dist/types';","symbol":"RecordType","correct":"import { RecordType } from 'avro-typescript';"},{"note":"For customizing generation, such as overriding logical types, import the `Options` interface to type the configuration object passed to `avroToTypeScript`.","symbol":"Options","correct":"import { Options } from 'avro-typescript';"}],"quickstart":{"code":"import { avroToTypeScript, RecordType } from 'avro-typescript';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Define a sample Avro schema (typically loaded from a .avsc file)\nconst avroSchema: RecordType = {\n  type: 'record',\n  name: 'UserProfile',\n  namespace: 'com.example.user',\n  fields: [\n    { name: 'id', type: 'string' },\n    { name: 'username', type: 'string' },\n    {\n      name: 'email',\n      type: ['null', 'string'],\n      default: null,\n    },\n    {\n      name: 'createdAt',\n      type: { type: 'long', logicalType: 'timestamp-millis' },\n    },\n    {\n      name: 'status',\n      type: {\n        type: 'enum',\n        name: 'UserStatus',\n        symbols: ['ACTIVE', 'INACTIVE', 'PENDING'],\n      },\n      default: 'PENDING',\n    },\n    {\n        name: 'tags',\n        type: { type: 'array', items: 'string' },\n        default: [],\n    },\n  ],\n};\n\n// Options for generating TypeScript, including logical type overrides\nconst generationOptions = {\n  logicalTypes: {\n    'timestamp-millis': 'Date',\n  },\n};\n\n// Generate TypeScript code\nconst typescriptCode = avroToTypeScript(avroSchema, generationOptions);\n\nconsole.log('Generated TypeScript:\\n');\nconsole.log(typescriptCode);\n\n// Example of writing to a file (optional)\nconst outputPath = path.join(process.cwd(), 'generated-types.d.ts');\nfs.writeFileSync(outputPath, typescriptCode);\nconsole.log(`\\nTypeScript types written to ${outputPath}`);\n\n/*\n  Expected output (simplified):\n\n  Generated TypeScript:\n\n  export namespace com.example.user {\n    export interface UserProfile {\n      id: string;\n      username: string;\n      email: string | null;\n      createdAt: Date;\n      status: UserStatus;\n      tags: string[];\n    }\n\n    export type UserStatus = 'ACTIVE' | 'INACTIVE' | 'PENDING';\n  }\n\n  TypeScript types written to .../generated-types.d.ts\n*/\n","lang":"typescript","description":"This quickstart demonstrates how to use `avro-typescript` to generate TypeScript interfaces from an Avro schema, including handling optional fields, enums, arrays, and logical type overrides to map Avro `timestamp-millis` to TypeScript `Date`."},"warnings":[{"fix":"Manually manage output file structure or use an external tool to wrap generated types in TypeScript namespaces if strict namespace isolation is required. Be aware of potential name collisions if schemas from different Avro namespaces define types with identical names.","message":"The library does not currently provide explicit support for Avro namespaces in the generated TypeScript output (e.g., creating nested modules or namespaces). While the Avro schema itself might define a `namespace`, the output interfaces will typically be at the top level or derive their names directly, potentially leading to name collisions if not managed carefully by the user. Other generators like `@ovotech/avro-ts` offer explicit namespace handling.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always pass a `logicalTypes` map in the options object to `avroToTypeScript` to explicitly define the desired TypeScript type for each logical type in your schema, e.g., `{ 'timestamp-millis': 'Date', 'date': 'string' }`.","message":"When using Avro logical types (e.g., `date`, `timestamp-millis`, `decimal`), `avro-typescript` will default to the underlying primitive Avro type (e.g., `int`, `long`, `bytes`) in the generated TypeScript if no `logicalTypes` override is provided in the options. This can lead to less precise types (e.g., `number` instead of `Date`).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Review generated types for fields with Avro defaults and manually mark them as optional (e.g., `field?: Type;`) in your codebase if strict type-checking of optionality based on Avro defaults is critical for your application logic.","message":"Avro schemas can define default values for fields, implying they are optional. While `avro-typescript` handles `null` in unions to make fields optional, it does not currently generate TypeScript types that reflect all Avro default values as optional fields in the interface. The `To-do` list indicates a future feature for 'Generate a function to set defaults as per the schema', suggesting full default value integration might be incomplete.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure that the generated TypeScript types are directly accessible without a namespace prefix, or if using a mix of generation tools, adjust your imports or manually wrap `avro-typescript` generated types into the expected namespace. Consider using unique type names across different Avro namespaces if direct namespace support is not available from your chosen generator.","cause":"This error often occurs when you're trying to reference a TypeScript type that you expect to be wrapped in a namespace corresponding to an Avro namespace, but `avro-typescript` (as of current versions) does not generate explicit TypeScript namespaces. Alternatively, it can happen if types generated by `avro-typescript` are used in conjunction with types generated by other Avro tools that *do* create namespaces, leading to a mismatch.","error":"TS2503: Cannot find namespace 'MyAvroNamespace'"},{"fix":"Validate your Avro schema independently using an Avro schema parser or linter before feeding it to `avro-typescript`. Ensure all referenced named types (records, enums, fixed) are correctly defined within the schema or imported if they reside in separate files (though `avro-typescript` expects a single, resolved schema object).","cause":"While not a direct TypeScript error, this is a common Avro schema parsing error that arises when the Avro schema itself is invalid, often due to a type referencing another type (`MyTypeName`) that hasn't been defined within the current schema or an imported schema. If `avro-typescript` receives such an invalid schema, its generation might fail or produce incorrect output.","error":"org.apache.avro.SchemaParseException: Undefined name: MyTypeName"}],"ecosystem":"npm"}