{"id":28297453,"url":"https://github.com/prime-run/go-style-errors","last_synced_at":"2026-02-23T01:31:59.753Z","repository":{"id":279739774,"uuid":"939789443","full_name":"prime-run/go-style-errors","owner":"prime-run","description":"Go-style error handling for TypeScript/JavaScript - Type-safe error handling with Result types","archived":false,"fork":false,"pushed_at":"2025-03-25T02:36:34.000Z","size":78,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-25T05:21:09.398Z","etag":null,"topics":["error-handling","react-error-capture","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"https://go-errors-docs.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prime-run.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2025-02-27T05:35:01.000Z","updated_at":"2025-03-25T02:36:37.000Z","dependencies_parsed_at":"2025-02-27T06:43:31.378Z","dependency_job_id":"43c4c824-b73b-4378-ad62-1396b364f061","html_url":"https://github.com/prime-run/go-style-errors","commit_stats":null,"previous_names":["ashkansamadiyan/go-style-errors","prime-run/go-style-errors"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/prime-run/go-style-errors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-run%2Fgo-style-errors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-run%2Fgo-style-errors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-run%2Fgo-style-errors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-run%2Fgo-style-errors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prime-run","download_url":"https://codeload.github.com/prime-run/go-style-errors/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-run%2Fgo-style-errors/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29734468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T20:09:16.275Z","status":"ssl_error","status_checked_at":"2026-02-22T20:09:13.750Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["error-handling","react-error-capture","typescript","typescript-library"],"created_at":"2025-05-23T02:14:59.754Z","updated_at":"2026-02-23T01:31:59.727Z","avatar_url":"https://github.com/prime-run.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-errors\n\nA lightweight, type-safe TypeScript library that brings Go-style error handling to JavaScript/TypeScript. Say goodbye to try-catch blocks and hello to elegant, functional error handling! This library brings the simplicity and elegance of Go's error handling pattern to your TypeScript/JavaScript projects.\n\n## Features\n\n- 🎯 **Type-safe**: Full TypeScript support with precise type inference\n- 🔄 **Unified API**: Same pattern for both sync and async operations\n- 🌐 **Fetch Support**: Built-in wrapper for fetch operations with transformers\n- 🪶 **Lightweight**: Zero dependencies, minimal overhead\n- 🔒 **Immutable**: Results are readonly tuples\n- 🎨 **Flexible**: Support for custom error types\n- 📦 **Tree-shakeable**: Only import what you need\n- 🔍 **Predictable**: No more try-catch spaghetti code\n- 🚀 **Fast**: Minimal runtime overhead\n- 💡 **Intuitive**: Familiar pattern for Go developers\n\n## Installation\n\n```bash\nbun add go-errors\n```\n\n## Quick Start\n\n```typescript\nimport { go } from 'go-errors';\n\n// Synchronous usage\nlet [value, err] = go(() =\u003e {\n  if (Math.random() \u003e 0.5) throw new Error('Bad luck!');\n  return 42;\n});\n\nif (err) {\n  console.error('Something went wrong:', err);\n} else {\n  console.log('Got value:', value);\n}\n\n// Asynchronous usage\nlet [data, err] = await go(fetch('https://api.example.com/data'));\n\nif (err) {\n  console.error('Failed to fetch:', err);\n} else {\n  console.log('Got data:', data);\n}\n```\n\n## Core Concepts\n\n### The Result Type\n\nThe library uses a tuple-based Result type that's similar to Go's multiple return values:\n\n```typescript\ntype Result\u003cT, E = Error\u003e = readonly [T, null] | readonly [null, E];\n```\n\nThis means a function will always return either:\n- `[value, null]` for success\n- `[null, error]` for failure\n\n### Variable Declaration Best Practice\n\nFollowing Go's convention, we recommend using `let` instead of `const` for result declarations. This allows you to reuse the error variable name (typically `err`) throughout your code, just like in Go:\n\n```typescript\n// ✅ Recommended: Using let\nlet [value, err] = go(() =\u003e someOperation());\nif (err) return handleError(err);\n\n// Another operation using the same err variable\nlet [result, err] = go(() =\u003e anotherOperation());\nif (err) return handleError(err);\n\n// ❌ Not recommended: Using const requires unique variable names\nconst [value1, error1] = go(() =\u003e someOperation());\nif (error1) return handleError(error1);\n\nconst [value2, error2] = go(() =\u003e anotherOperation());\nif (error2) return handleError(error2);\n```\n\n### Main Functions\n\n#### 1. `go\u003cT, E = Error\u003e`\n\nThe main function that handles both synchronous and asynchronous operations:\n\n```typescript\n// Synchronous\nlet [value, err] = go(() =\u003e someOperation());\n\n// Asynchronous\nlet [value, err] = await go(somePromise);\n\n// With custom error types\nlet [value, err] = go\u003cnumber, CustomError\u003e(() =\u003e validate(input));\n```\n\n#### 2. `goFetch\u003cT, E = string\u003e`\n\nA powerful fetch wrapper with built-in error handling and transformation capabilities:\n\n```typescript\ninterface User {\n  id: number;\n  name: string;\n}\n\n// Basic usage\nlet [user, err] = await goFetch\u003cUser\u003e('https://api.example.com/user/1');\n\n// Advanced usage with options\nlet [user, err] = await goFetch\u003cUser\u003e('https://api.example.com/user/1', {\n  // Request options (extends Fetch API options)\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({ name: 'John' }),\n  \n  // Response transformation\n  responseTransformer: (data: unknown) =\u003e ({\n    ...data as User,\n    lastFetched: new Date()\n  }),\n  \n  // Error transformation\n  errorTransformer: (error: unknown) =\u003e {\n    if (error instanceof Error) {\n      return `API Error: ${error.message}`;\n    }\n    return 'Unknown error occurred';\n  }\n});\n```\n\n##### goFetch Options\n\nThe `goFetch` function accepts an optional options object that extends the standard Fetch API options:\n\n```typescript\ninterface GoFetchOptions\u003cT = any, E = string\u003e extends RequestInit {\n  // Transform the response data before returning\n  responseTransformer?: (data: unknown) =\u003e T;\n  \n  // Transform errors into your preferred format\n  errorTransformer?: (error: unknown) =\u003e E;\n  \n  // All standard fetch options are supported\n  method?: string;\n  headers?: HeadersInit;\n  body?: BodyInit;\n  mode?: RequestMode;\n  credentials?: RequestCredentials;\n  cache?: RequestCache;\n  // ... and more\n}\n```\n\n## Advanced Usage\n\n### Custom Error Types\n\nYou can specify custom error types for more precise error handling:\n\n```typescript\nclass ValidationError extends Error {\n  constructor(public field: string, message: string) {\n    super(message);\n  }\n}\n\nlet [value, err] = go\u003cnumber, ValidationError\u003e(() =\u003e {\n  if (input \u003c 0) throw new ValidationError('input', 'Must be positive');\n  return input * 2;\n});\n\nif (err) {\n  console.error(`Validation failed for ${err.field}: ${err.message}`);\n}\n```\n\n### Complex API Interactions\n\n```typescript\ninterface ApiResponse\u003cT\u003e {\n  data: T;\n  status: string;\n  metadata: {\n    timestamp: string;\n    version: string;\n  };\n}\n\ninterface ApiError {\n  code: number;\n  message: string;\n  details?: string;\n}\n\ninterface User {\n  id: number;\n  name: string;\n  email: string;\n}\n\nasync function fetchUserData(userId: string) {\n  let [user, err] = await goFetch\u003cApiResponse\u003cUser\u003e, ApiError\u003e(\n    `https://api.example.com/user/${userId}`,\n    {\n      headers: {\n        'Authorization': 'Bearer token',\n      },\n      responseTransformer: (data: unknown) =\u003e {\n        const response = data as ApiResponse\u003cUser\u003e;\n        // Add custom validation\n        if (!response.data.id) {\n          throw new Error('Invalid user data');\n        }\n        return response;\n      },\n      errorTransformer: (error: unknown) =\u003e {\n        if (error instanceof Error) {\n          return {\n            code: 500,\n            message: error.message,\n            details: error.stack\n          };\n        }\n        return {\n          code: 400,\n          message: 'Unknown error'\n        };\n      },\n    }\n  );\n\n  if (err) {\n    console.error(`API Error ${err.code}: ${err.message}`);\n    return [null, err] as const;\n  }\n\n  return [user.data, null] as const;\n}\n```\n\n### Error Handling Patterns\n\n#### Sequential Operations\n\n```typescript\nasync function processUserData(userId: string) {\n  // Fetch user\n  let [user, err] = await goFetch\u003cUser\u003e(`/api/users/${userId}`);\n  if (err) return [null, err] as const;\n\n  // Fetch user's posts\n  let [posts, err] = await goFetch\u003cPost[]\u003e(`/api/users/${userId}/posts`);\n  if (err) return [null, err] as const;\n\n  // Process everything\n  let [result, err] = go(() =\u003e ({\n    user,\n    posts,\n    timestamp: new Date()\n  }));\n  \n  return [result, err] as const;\n}\n```\n\n#### Parallel Operations\n\n```typescript\nasync function fetchUserDashboard(userId: string) {\n  // Fetch multiple resources in parallel\n  let [results, err] = await go(Promise.all([\n    goFetch\u003cUser\u003e(`/api/users/${userId}`),\n    goFetch\u003cPost[]\u003e(`/api/users/${userId}/posts`),\n    goFetch\u003cActivity[]\u003e(`/api/users/${userId}/activity`)\n  ]));\n\n  if (err) return [null, err] as const;\n\n  const [[user, userErr], [posts, postsErr], [activity, activityErr]] = results;\n\n  // Check for individual errors\n  if (userErr || postsErr || activityErr) {\n    return [null, new Error('Failed to fetch some dashboard data')] as const;\n  }\n\n  return [{\n    user,\n    posts,\n    activity,\n    lastUpdated: new Date()\n  }, null] as const;\n}\n```\n\n## Best Practices\n\n1. **Always Check for Errors First**\n   ```typescript\n   let [data, err] = await go(fetchData());\n   if (err) {\n     // Handle error first\n     return handleError(err);\n   }\n   // Then work with data\n   processData(data);\n   ```\n\n2. **Use Type Parameters for Better Type Safety**\n   ```typescript\n   let [value, err] = go\u003cnumber, CustomError\u003e(() =\u003e validate(input));\n   ```\n\n3. **Avoid Nested Error Handling**\n   ```typescript\n   // Good\n   let [data, err] = await go(step1());\n   if (err) return handleError(err);\n   \n   let [result, err] = await go(step2(data));\n   if (err) return handleError(err);\n   \n   // Not recommended\n   let [data, err] = await go(step1());\n   if (!err) {\n     let [result, err] = await go(step2(data));\n     if (!err) {\n       // ...\n     }\n   }\n   ```\n\n4. **Use Consistent Error Types**\n   ```typescript\n   // Define your error types\n   type AppError = ValidationError | DatabaseError | NetworkError;\n\n   // Use them consistently\n   let [data, err] = go\u003cData, AppError\u003e(() =\u003e processData());\n   ```\n\n5. **Propagate Errors Up**\n   ```typescript\n   function processData(): GoResult\u003cProcessedData, AppError\u003e {\n     let [data, err] = getData();\n     if (err) return [null, err] as const;\n\n     let [processed, err] = go(() =\u003e transform(data));\n     if (err) return [null, err] as const;\n\n     return [processed, null] as const;\n   }\n   ```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## License\n\nMIT License - see the [LICENSE](LICENSE) file for details.\n\n## Credits\n\nCreated by Ashkan Samadiyan\n\n---\n\nMade with ❤️ for the TypeScript community ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprime-run%2Fgo-style-errors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprime-run%2Fgo-style-errors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprime-run%2Fgo-style-errors/lists"}