{"id":15168995,"url":"https://github.com/bloomberg/ts-blank-space","last_synced_at":"2025-05-14T07:11:06.827Z","repository":{"id":257763345,"uuid":"844646745","full_name":"bloomberg/ts-blank-space","owner":"bloomberg","description":"A small, fast, pure JavaScript type-stripper that uses the official TypeScript parser.","archived":false,"fork":false,"pushed_at":"2025-03-03T10:02:27.000Z","size":2028,"stargazers_count":790,"open_issues_count":4,"forks_count":17,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-05-13T19:16:00.616Z","etag":null,"topics":["javascript","type-stripping","typescript"],"latest_commit_sha":null,"homepage":"https://bloomberg.github.io/ts-blank-space","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/bloomberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/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-08-19T17:26:29.000Z","updated_at":"2025-05-13T10:07:10.000Z","dependencies_parsed_at":"2024-09-18T15:06:58.551Z","dependency_job_id":"5f5a8832-346f-4072-8c71-e52591451401","html_url":"https://github.com/bloomberg/ts-blank-space","commit_stats":{"total_commits":184,"total_committers":7,"mean_commits":"26.285714285714285","dds":0.07608695652173914,"last_synced_commit":"fa37b5e77b3294fe13e1fc65f2ba785fc3110cfb"},"previous_names":["bloomberg/ts-blank-space"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fts-blank-space","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fts-blank-space/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fts-blank-space/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fts-blank-space/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bloomberg","download_url":"https://codeload.github.com/bloomberg/ts-blank-space/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092798,"owners_count":22013292,"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":["javascript","type-stripping","typescript"],"created_at":"2024-09-27T07:00:44.536Z","updated_at":"2025-05-14T07:11:01.817Z","avatar_url":"https://github.com/bloomberg.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Loaders / Execution Tools"],"sub_categories":[],"readme":"\u003ca href=\"https://bloomberg.github.io/ts-blank-space\"\u003e\n    \u003cimg src=\"assets/ts-blank-space.png\" width=\"728\" alt=\"'ts-blank-space' as a logo. the 'ts' is in TypeScript blue and the 'blank-space' is in JavaScript orange\" /\u003e\n\u003c/a\u003e\n\nA small, fast, pure JavaScript type-stripper that uses the official TypeScript parser.\n\n[![npm Badge](https://img.shields.io/npm/v/ts-blank-space.svg)](https://www.npmjs.com/package/ts-blank-space)\n\n---\n\nTypeScript goes in:\n\n\u003c!-- prettier-ignore --\u003e\n```typescript\nclass C\u003cT\u003e extends Array\u003cT\u003e implements I {\n//     ^^^              ^^^^^^^^^^^^^^^^\n    private field!: string;\n//  ^^^^^^^      ^^^^^^^^^\n\n    method\u003cT\u003e(this: T, a?: string): void {\n//        ^^^ ^^^^^^^^  ^^^^^^^^^ ^^^^^^\n    }\n}\n```\n\nJavaScript + space comes out:\n\n\u003c!-- prettier-ignore --\u003e\n```javascript\nclass C    extends Array                 {\n//     ^^^              ^^^^^^^^^^^^^^^^\n            field         ;\n//  ^^^^^^^      ^^^^^^^^^\n\n    method   (         a         )       {\n//        ^^^ ^^^^^^^^  ^^^^^^^^^ ^^^^^^\n    }\n}\n```\n\nTry it out in the [playground](https://bloomberg.github.io/ts-blank-space/play/).\n\n## Rationale\n\nThe benefits of this library are:\n\n-   It is fast\n    -   See [`./perf`](./perf/) folder for a micro-benchmark\n        -   Only 4 times slower than a native multi-threaded transformer\n        -   Fastest compared to non-native (JavaScript or Wasm)\n    -   No new JavaScript code is generated; instead, it re-uses slices of the existing source string\n    -   This is particularly true if your program is already generating the TypeScript `SourceFile` object, because it can [be reused](#bring-your-own-ast) -- and producing the AST is the most time consuming part.\n-   100% JavaScript runtime\n    -   No [Wasm](https://webassembly.org)\n    -   No [native-addons](https://nodejs.org/api/addons.html)\n    -   No [child process](https://nodejs.org/api/child_process.html)\n-   It is small\n    -   Around 700 lines of code and one dependency ([`TypeScript`](https://www.npmjs.com/package/typescript))\n    -   By doing so little, the code should be relatively easy to maintain\n-   Delegates the parsing to the [official TypeScript parser](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API)\n-   No need for additional SourceMap processing; see [\"where are my SourceMaps?\"](#where-are-my-sourcemaps)\n\n:information_source: Not all TypeScript syntax is supported (see [unsupported syntax](#unsupported-syntax)). There is also no down-leveling; the JavaScript is preserved as is.\n\n## Contents\n\n-   [Installing](#installing)\n-   [API](#api)\n-   [Node.js Loader](#nodejs-loader)\n-   [SourceMaps](#where-are-my-sourcemaps)\n-   [Implementation details](#does-it-really-just-blank-out-all-the-type-annotations)\n-   [Unsupported Syntax](#unsupported-syntax)\n-   [tsconfig.json](#recommended-tsconfigjson-compiler-settings)\n-   [TSX/JSX](#tsxjsx)\n-   [ESM Output](#ensuring-esm-output)\n-   [Contributions](#contributions)\n-   [License](#license)\n-   [Code of Conduct](#code-of-conduct)\n-   [Security Vulnerability Reporting](#security-vulnerability-reporting)\n\n## Installing\n\n```sh\nnpm install ts-blank-space\n```\n\n## API\n\n### String to String\n\n```typescript\nexport default function tsBlankSpace(ts: string, onError?: (node) =\u003e void): string;\n```\n\n```javascript\nimport tsBlankSpace from \"ts-blank-space\";\n\nconsole.log(tsBlankSpace(`let x: string;`));\n// \"let x        ;\"\n```\n\n### Bring your own AST\n\n```typescript\nexport function blankSourceFile(ts: typescript.SourceFile, onError?: (node) =\u003e void): string;\n```\n\n```javascript\nimport ts from \"typescript\";\nimport { blankSourceFile } from \"ts-blank-space\";\n\nconst ast = ts.createSourceFile(...);\nconsole.log(blankSourceFile(ast));\n```\n\n## Node.js Loader\n\n`ts-blank-space` exposes the required [Node.js module loader hooks](https://nodejs.org/api/module.html#customization-hooks) to use `ts-blank-space` to pre-process `*.ts` that are imported before they are evaluated.\n\n```sh\n# Install (one time):\n$ npm install --save-dev ts-blank-space\n\n# Example usage (Node.js \u003e= v18.20):\n$ node --import ts-blank-space/register ./path/to/your/file.ts\n```\n\nIn addition to loading `*.ts` files, an import resolver is also registered which catches failed `*.js` imports and re-attempts the import replacing the extension with `.ts`. This allows import paths to choose either `.ts` or `.js` depending on which other factors the project may need to take into account such as bundling and package distribution.\n\n:information_source: The loader assumes that all `.ts` files are [ESM](https://nodejs.org/api/esm.html).\n\n## Where are my SourceMaps?\n\nBecause all the JavaScript in the output is located at the same line, column, and byte-offset as the original source, no mapping information is lost during the transform.\n\n## Does it really just blank out all the type annotations?\n\nThere are two cases, described here, where it does more than replace the TypeScript syntax with blank space.\n\n### ASI (automatic semicolon insertion)\n\nTo guard against [ASI](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion) issues in the output, `ts-blank-space` will add `;` to the end of type-only statements, and when removing a leading type annotation could introduce an ASI hazard.\n\n#### Example one - type-only statement\n\n\u003c!-- prettier-ignore --\u003e\n```typescript\nstatementWithNoSemiColon\ntype Erased = true\n(\"not calling above statement\")\n```\n\nbecomes:\n\n\u003c!-- prettier-ignore --\u003e\n```javascript\nstatementWithNoSemiColon\n;\n(\"not calling above statement\");\n```\n\n#### Example two - computed class fields/methods\n\n\u003c!-- prettier-ignore --\u003e\n```typescript\nclass C {\n    field = 1/* no ; */\n    public [\"computed field not accessing above\"] = 2\n}\n```\n\nbecomes:\n\n\u003c!-- prettier-ignore --\u003e\n```javascript\nclass C {\n    field = 1/* no ; */\n    ;      [\"computed field not accessing above\"] = 2\n}\n```\n\n### Arrow function type annotations that introduce a new line\n\nIf the type annotations around an arrow function's parameters introduce a new line then only replacing them with blank space can be incorrect. Therefore, in addition to removing the type annotation, the `(` or `)` surrounding the function parameters may also be moved.\n\n#### Example one - multi-line return type:\n\n\u003c!-- prettier-ignore --\u003e\n```typescript\nlet f = (a: string, b: string): Array\u003c\n   string\n\u003e =\u003e [a, b];\n```\n\nbecomes:\n\n\u003c!-- prettier-ignore --\u003e\n```javascript\nlet f = (a        , b\n\n) =\u003e [a, b];\n```\n\n#### Example two - `async` with multi-line type arguments:\n\n\u003c!-- prettier-ignore --\u003e\n```typescript\nlet f = async \u003c\n    T\n\u003e(v: T) =\u003e {};\n```\n\nbecomes:\n\n\u003c!-- prettier-ignore --\u003e\n```javascript\nlet f = async (\n\n  v   ) =\u003e {};\n```\n\n## Unsupported Syntax\n\nSome parts of TypeScript are not supported because they can't be erased in place due to having runtime semantics. See [unsupported_syntax.md](./docs/unsupported_syntax.md).\n\nWhen unsupported syntax is encountered, `ts-blank-space` will call the optional `onError` callback and continue. Examples can be seen in [`errors.test.ts`](./tests/errors.test.ts).\n\n## Recommended `tsconfig.json` compiler settings\n\n```jsonc\n{\n    // Because JS syntax is emitted as-is\n    \"target\": \"esnext\",\n    // Because class fields are preserved as written which corresponds\n    // to 'define' semantics in the ECMAScript specification\n    \"useDefineForClassFields\": true,\n    // Because imports and exports are preserved as written, only removing the\n    // parts which are explicitly annotated with the `type` keyword\n    \"verbatimModuleSyntax\": true,\n    // As of `typescript@5.8` there is a built-in check to error on the non-erasable\n    // syntax that tools such as `ts-blank-space` don't support e.g. parameter properties.\n    \"erasableSyntaxOnly\": true,\n}\n```\n\n## TSX/JSX\n\n`.tsx` input will generate `.jsx` output. JSX parts are not transformed, but instead preserved in the output.\n\nBy default, `ts-blank-space` will parse the file assuming `.ts`. If the original file contains JSX syntax, then the [parsing should be done manually](#bring-your-own-ast). There is a TSX example in [`valid.test.ts`](./tests/valid.test.ts).\n\n```typescript\nimport ts from \"typescript\";\nimport { blankSourceFile } from \"ts-blank-space\";\n\n...\n\nconst tsxSource = ts.createSourceFile(\"input.tsx\", tsxInput, ts.ScriptTarget.ESNext, false, ts.ScriptKind.TSX);\nconst jsxOutput = blankSourceFile(tsxSource, onError);\n```\n\n## Ensuring ESM output\n\nTypeScript may add an `export {};` if all `import`s and `export`s were removed (because they were `import/export type`).\n\nBecause `ts-blank-space` only removes code, this is not performed. To force the output to always have an ESM syntactic marker, you can manually append `\"export {};\"`;\n\n## 3rd party ecosystem plugins\n\n-   Webpack/Rspack: [ts-blank-loader](https://github.com/leimonio/ts-blank-loader)\n\n## Contributions\n\nWe :heart: contributions.\n\nHave you had a good experience with this project? Why not share some love and contribute code, or just let us know about any issues you had with it?\n\nWe welcome issue reports [here](../../issues); be sure to choose the proper issue template for your issue, so that we can be sure you're providing the necessary information.\n\nBefore sending a [Pull Request](../../pulls), please make sure you read our\n[Contribution Guidelines](https://github.com/bloomberg/.github/blob/main/CONTRIBUTING.md).\n\n## License\n\nPlease read the [LICENSE](./LICENSE) file.\n\n## Code of Conduct\n\nThis project has adopted a [Code of Conduct](https://github.com/bloomberg/.github/blob/main/CODE_OF_CONDUCT.md).\nIf you have any concerns about the Code, or behavior which you have experienced in the project, please\ncontact us at opensource@bloomberg.net.\n\n## Security Vulnerability Reporting\n\nPlease refer to the project [Security Policy](https://github.com/bloomberg/.github/blob/main/SECURITY.MD).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Fts-blank-space","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbloomberg%2Fts-blank-space","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Fts-blank-space/lists"}