├── .gitignore ├── .vscode └── settings.json ├── src ├── bin.ts ├── model.ts ├── config.ts └── command.ts ├── docs └── tsconfig │ ├── verbose.md │ ├── clean.md │ ├── generateTrace.md │ ├── force.md │ ├── newLine.md │ ├── stopBuildOnErrors.md │ ├── noCheck.md │ ├── preserveWatchOutput.md │ ├── skipDefaultLibCheck.md │ ├── strictBuiltinIteratorReturn.md │ ├── enable.md │ ├── reactNamespace.md │ ├── pretty.md │ ├── out.md │ ├── noImplicitUseStrict.md │ ├── traceResolution.md │ ├── excludeFiles.md │ ├── charset.md │ ├── disableSizeLimit.md │ ├── noUnusedLocals.md │ ├── emitDeclarationOnly.md │ ├── isolatedDeclarations.md │ ├── declarationMap.md │ ├── noUnusedParameters.md │ ├── emitBOM.md │ ├── noEmitOnError.md │ ├── alwaysStrict.md │ ├── resolvePackageJsonExports.md │ ├── excludeDirectories.md │ ├── noImplicitReturns.md │ ├── diagnostics.md │ ├── disableSolutionSearching.md │ ├── noLib.md │ ├── rewriteRelativeImportExtensions.md │ ├── extendedDiagnostics.md │ ├── noStrictGenericChecks.md │ ├── keyofStringsOnly.md │ ├── noEmit.md │ ├── noResolve.md │ ├── resolvePackageJsonImports.md │ ├── references.md │ ├── allowUmdGlobalAccess.md │ ├── synchronousWatchDirectory.md │ ├── disableSourceOfProjectReferenceRedirect.md │ ├── disableReferencedProjectLoad.md │ ├── mapRoot.md │ ├── outFile.md │ ├── allowImportingTsExtensions.md │ ├── sourceRoot.md │ ├── disableFilenameBasedTypeAcquisition.md │ ├── allowUnusedLabels.md │ ├── watchDirectory.md │ ├── noFallthroughCasesInSwitch.md │ ├── forceConsistentCasingInFileNames.md │ ├── strict.md │ ├── experimentalDecorators.md │ ├── useDefineForClassFields.md │ ├── exclude.md │ ├── incremental.md │ ├── assumeChangesOnlyAffectDirectDependencies.md │ ├── files.md │ ├── maxNodeModuleJsDepth.md │ ├── declarationDir.md │ ├── preserveSymlinks.md │ ├── noImplicitAny.md │ ├── suppressExcessPropertyErrors.md │ ├── noImplicitThis.md │ ├── watchFile.md │ ├── typeRoots.md │ ├── suppressImplicitAnyIndexErrors.md │ ├── generateCpuProfile.md │ ├── strictPropertyInitialization.md │ ├── baseUrl.md │ ├── moduleSuffixes.md │ ├── moduleDetection.md │ ├── useUnknownInCatchVariables.md │ ├── composite.md │ ├── outDir.md │ ├── preserveValueImports.md │ ├── removeComments.md │ ├── strictBindCallApply.md │ ├── importsNotUsedAsValues.md │ ├── allowUnreachableCode.md │ ├── locale.md │ ├── fallbackPolling.md │ ├── listEmittedFiles.md │ ├── tsBuildInfoFile.md │ ├── noEmitHelpers.md │ ├── listFiles.md │ ├── inlineSourceMap.md │ ├── typeAcquisition.md │ ├── declaration.md │ ├── resolveJsonModule.md │ ├── libReplacement.md │ ├── checkJs.md │ ├── inlineSources.md │ ├── sourceMap.md │ ├── plugins.md │ ├── moduleResolution.md │ ├── allowJs.md │ ├── target.md │ ├── noErrorTruncation.md │ ├── noUncheckedIndexedAccess.md │ ├── skipLibCheck.md │ ├── paths.md │ ├── customConditions.md │ ├── jsxFactory.md │ ├── strictFunctionTypes.md │ ├── jsxFragmentFactory.md │ ├── extends.md │ ├── importHelpers.md │ ├── types.md │ ├── exactOptionalPropertyTypes.md │ ├── stripInternal.md │ ├── allowSyntheticDefaultImports.md │ ├── noPropertyAccessFromIndexSignature.md │ ├── explainFiles.md │ ├── noImplicitOverride.md │ ├── preserveConstEnums.md │ ├── emitDecoratorMetadata.md │ ├── allowArbitraryExtensions.md │ ├── strictNullChecks.md │ ├── include.md │ ├── rootDirs.md │ ├── rootDir.md │ ├── noUncheckedSideEffectImports.md │ ├── erasableSyntaxOnly.md │ ├── jsxImportSource.md │ ├── isolatedModules.md │ ├── jsx.md │ ├── esModuleInterop.md │ ├── downlevelIteration.md │ ├── module.md │ ├── lib.md │ └── verbatimModuleSyntax.md ├── .prettierrc ├── .changeset ├── config.json └── README.md ├── .github └── workflows │ └── ci.yml ├── prompts ├── hows-my-tsconfig-score.md └── hows-my-tsconfig.md ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /src/bin.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { command } from './command.ts'; 4 | 5 | command.parse(process.argv); 6 | -------------------------------------------------------------------------------- /docs/tsconfig/verbose.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Verbose' 3 | oneline: 'Enable verbose logging.' 4 | --- 5 | 6 | Enable verbose logging 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "printWidth": 80, 6 | "tabWidth": 2 7 | } 8 | -------------------------------------------------------------------------------- /docs/tsconfig/clean.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Clean' 3 | oneline: 'Delete the outputs of all projects.' 4 | --- 5 | 6 | Delete the outputs of all projects 7 | -------------------------------------------------------------------------------- /docs/tsconfig/generateTrace.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'generateTrace' 3 | oneline: 'Generates an event trace and a list of types.' 4 | --- 5 | 6 | Generates an event trace and a list of types. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/force.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Force' 3 | oneline: 'Build all projects, including those that appear to be up to date.' 4 | --- 5 | 6 | Build all projects, including those that appear to be up to date 7 | -------------------------------------------------------------------------------- /docs/tsconfig/newLine.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'New Line' 3 | oneline: 'Set the newline character for emitting files.' 4 | --- 5 | 6 | Specify the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix). 7 | -------------------------------------------------------------------------------- /docs/tsconfig/stopBuildOnErrors.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'stopBuildOnErrors' 3 | oneline: 'Skip building downstream projects on error in upstream project.' 4 | --- 5 | 6 | Skip building downstream projects on error in upstream project. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/noCheck.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'noCheck' 3 | oneline: 'Disable full type checking (only critical parse and emit errors will be reported).' 4 | --- 5 | 6 | Disable full type checking (only critical parse and emit errors will be reported). 7 | -------------------------------------------------------------------------------- /docs/tsconfig/preserveWatchOutput.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Preserve Watch Output' 3 | oneline: 'Disable wiping the console in watch mode.' 4 | --- 5 | 6 | Whether to keep outdated console output in watch mode instead of clearing the screen every time a change happened. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/skipDefaultLibCheck.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Skip Default Lib Check' 3 | oneline: 'Skip type checking .d.ts files that are included with TypeScript.' 4 | --- 5 | 6 | Use [`skipLibCheck`](#skipLibCheck) instead. Skip type checking of default library declaration files. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/strictBuiltinIteratorReturn.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'strictBuiltinIteratorReturn' 3 | oneline: 'Built-in iterators are instantiated with a TReturn type of undefined instead of any.' 4 | --- 5 | 6 | Built-in iterators are instantiated with a `TReturn` type of undefined instead of `any`. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/enable.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Enable' 3 | oneline: 'Disable the type acquisition for JavaScript projects.' 4 | --- 5 | 6 | Disables automatic type acquisition in JavaScript projects: 7 | 8 | ```json 9 | { 10 | "typeAcquisition": { 11 | "enable": false 12 | } 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/tsconfig/reactNamespace.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'React Namespace' 3 | oneline: 'Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit.' 4 | --- 5 | 6 | Use [`jsxFactory`](#jsxFactory) instead. Specify the object invoked for `createElement` when targeting `react` for TSX files. 7 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.2/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": true, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /docs/tsconfig/pretty.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Pretty' 3 | oneline: "Enable color and formatting in TypeScript's output to make compiler errors easier to read." 4 | --- 5 | 6 | Stylize errors and messages using color and context, this is on by default — offers you a chance to have less terse, 7 | single colored messages from the compiler. 8 | -------------------------------------------------------------------------------- /docs/tsconfig/out.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Out' 3 | oneline: 'Deprecated setting. Use [`outFile`](#outFile) instead.' 4 | --- 5 | 6 | Use [`outFile`](#outFile) instead. 7 | 8 | The `out` option computes the final file location in a way that is not predictable or consistent. 9 | This option is retained for backward compatibility only and is deprecated. 10 | -------------------------------------------------------------------------------- /docs/tsconfig/noImplicitUseStrict.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Implicit Use Strict' 3 | oneline: "Disable adding 'use strict' directives in emitted JavaScript files." 4 | --- 5 | 6 | You shouldn't need this. By default, when emitting a module file to a non-ES6 target, TypeScript emits a `"use strict";` prologue at the top of the file. 7 | This setting disables the prologue. 8 | -------------------------------------------------------------------------------- /docs/tsconfig/traceResolution.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Trace Resolution' 3 | oneline: 'Log paths used during the [`moduleResolution`](#moduleResolution) process.' 4 | --- 5 | 6 | When you are trying to debug why a module isn't being included. 7 | You can set `traceResolution` to `true` to have TypeScript print information about its resolution process for each processed file. 8 | -------------------------------------------------------------------------------- /docs/tsconfig/excludeFiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Exclude Files' 3 | oneline: "Remove a list of files from the watch mode's processing." 4 | --- 5 | 6 | You can use `excludeFiles` to remove a set of specific files from the files which are watched. 7 | 8 | ```json tsconfig 9 | { 10 | "watchOptions": { 11 | "excludeFiles": ["temp/file.ts"] 12 | } 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/tsconfig/charset.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Charset' 3 | oneline: 'No longer supported. In early versions, manually set the text encoding for reading files.' 4 | --- 5 | 6 | In prior versions of TypeScript, this controlled what encoding was used when reading text files from disk. 7 | Today, TypeScript assumes UTF-8 encoding, but will correctly detect UTF-16 (BE and LE) or UTF-8 BOMs. 8 | -------------------------------------------------------------------------------- /docs/tsconfig/disableSizeLimit.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Disable Size Limit' 3 | oneline: 'Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server.' 4 | --- 5 | 6 | To avoid a possible memory bloat issues when working with very large JavaScript projects, there is an upper limit to the amount of memory TypeScript will allocate. Turning this flag on will remove the limit. 7 | -------------------------------------------------------------------------------- /docs/tsconfig/noUnusedLocals.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Unused Locals' 3 | oneline: "Enable error reporting when local variables aren't read." 4 | --- 5 | 6 | Report errors on unused local variables. 7 | 8 | ```ts twoslash 9 | // @noUnusedLocals 10 | // @errors: 6133 11 | const createKeyboard = (modelID: number) => { 12 | const defaultModelID = 23; 13 | return { type: 'keyboard', modelID }; 14 | }; 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/tsconfig/emitDeclarationOnly.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Emit Declaration Only' 3 | oneline: 'Only output d.ts files and not JavaScript files.' 4 | --- 5 | 6 | _Only_ emit `.d.ts` files; do not emit `.js` files. 7 | 8 | This setting is useful in two cases: 9 | 10 | - You are using a transpiler other than TypeScript to generate your JavaScript. 11 | - You are using TypeScript to only generate `d.ts` files for your consumers. 12 | -------------------------------------------------------------------------------- /docs/tsconfig/isolatedDeclarations.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'isolatedDeclarations' 3 | oneline: 'Require sufficient annotation on exports so other tools can trivially generate declaration files.' 4 | --- 5 | 6 | Require sufficient annotation on exports so other tools can trivially generate declaration files. 7 | 8 | For more information, see the [5.5 release notes](/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations) 9 | -------------------------------------------------------------------------------- /docs/tsconfig/declarationMap.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Declaration Map' 3 | oneline: 'Create sourcemaps for d.ts files.' 4 | --- 5 | 6 | Generates a source map for `.d.ts` files which map back to the original `.ts` source file. 7 | This will allow editors such as VS Code to go to the original `.ts` file when using features like _Go to Definition_. 8 | 9 | You should strongly consider turning this on if you're using project references. 10 | -------------------------------------------------------------------------------- /docs/tsconfig/noUnusedParameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Unused Parameters' 3 | oneline: "Raise an error when a function parameter isn't read." 4 | --- 5 | 6 | Report errors on unused parameters in functions. 7 | 8 | ```ts twoslash 9 | // @noUnusedParameters 10 | // @errors: 6133 11 | const createDefaultKeyboard = (modelID: number) => { 12 | const defaultModelID = 23; 13 | return { type: 'keyboard', modelID: defaultModelID }; 14 | }; 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/tsconfig/emitBOM.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Emit BOM' 3 | oneline: 'Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.' 4 | --- 5 | 6 | Controls whether TypeScript will emit a [byte order mark (BOM)](https://wikipedia.org/wiki/Byte_order_mark) when writing output files. 7 | Some runtime environments require a BOM to correctly interpret a JavaScript files; others require that it is not present. 8 | The default value of `false` is generally best unless you have a reason to change it. 9 | -------------------------------------------------------------------------------- /docs/tsconfig/noEmitOnError.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Emit On Error' 3 | oneline: 'Disable emitting files if any type checking errors are reported.' 4 | --- 5 | 6 | Do not emit compiler output files like JavaScript source code, source-maps or declarations if any errors were reported. 7 | 8 | This defaults to `false`, making it easier to work with TypeScript in a watch-like environment where you may want to see results of changes to your code in another environment before making sure all errors are resolved. 9 | -------------------------------------------------------------------------------- /docs/tsconfig/alwaysStrict.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Always Strict' 3 | oneline: "Ensure 'use strict' is always emitted." 4 | --- 5 | 6 | Ensures that your files are parsed in the ECMAScript strict mode, and emit "use strict" for each source file. 7 | 8 | [ECMAScript strict](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Strict_mode) mode was introduced in ES5 and provides behavior tweaks to the runtime of the JavaScript engine to improve performance, and makes a set of errors throw instead of silently ignoring them. 9 | -------------------------------------------------------------------------------- /docs/tsconfig/resolvePackageJsonExports.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Resolve package.json Exports' 3 | oneline: "Use the package.json 'exports' field when resolving package imports." 4 | --- 5 | 6 | `--resolvePackageJsonExports` forces TypeScript to consult [the `exports` field of `package.json` files](https://nodejs.org/api/packages.html#exports) if it ever reads from a package in `node_modules`. 7 | 8 | This option defaults to `true` under the `node16`, `nodenext`, and `bundler` options for [`--moduleResolution`](#moduleResolution). 9 | -------------------------------------------------------------------------------- /docs/tsconfig/excludeDirectories.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Exclude Directories' 3 | oneline: 'Remove a list of directories from the watch process.' 4 | --- 5 | 6 | You can use [`excludeFiles`](#excludeFiles) to drastically reduce the number of files which are watched during `--watch`. This can be a useful way to reduce the number of open file which TypeScript tracks on Linux. 7 | 8 | ```json tsconfig 9 | { 10 | "watchOptions": { 11 | "excludeDirectories": ["**/node_modules", "_build", "temp/*"] 12 | } 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/tsconfig/noImplicitReturns.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Implicit Returns' 3 | oneline: 'Enable error reporting for codepaths that do not explicitly return in a function.' 4 | --- 5 | 6 | When enabled, TypeScript will check all code paths in a function to ensure they return a value. 7 | 8 | ```ts twoslash 9 | // @errors: 2366 2322 10 | function lookupHeadphonesManufacturer(color: 'blue' | 'black'): string { 11 | if (color === 'blue') { 12 | return 'beats'; 13 | } else { 14 | ('bose'); 15 | } 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/tsconfig/diagnostics.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Diagnostics' 3 | oneline: 'Output compiler performance information after building.' 4 | --- 5 | 6 | Used to output diagnostic information for debugging. This command is a subset of [`extendedDiagnostics`](#extendedDiagnostics) which are more user-facing results, and easier to interpret. 7 | 8 | If you have been asked by a TypeScript compiler engineer to give the results using this flag in a compile, in which there is no harm in using [`extendedDiagnostics`](#extendedDiagnostics) instead. 9 | -------------------------------------------------------------------------------- /docs/tsconfig/disableSolutionSearching.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Disable Solution Searching' 3 | oneline: 'Opt a project out of multi-project reference checking when editing.' 4 | --- 5 | 6 | When working with [composite TypeScript projects](/docs/handbook/project-references.html), this option provides a way to declare that you do not want a project to be included when using features like _find all references_ or _jump to definition_ in an editor. 7 | 8 | This flag is something you can use to increase responsiveness in large composite projects. 9 | -------------------------------------------------------------------------------- /docs/tsconfig/noLib.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Lib' 3 | oneline: 'Disable including any library files, including the default lib.d.ts.' 4 | --- 5 | 6 | Disables the automatic inclusion of any library files. 7 | If this option is set, `lib` is ignored. 8 | 9 | TypeScript _cannot_ compile anything without a set of interfaces for key primitives like: `Array`, `Boolean`, `Function`, `IArguments`, `Number`, `Object`, `RegExp`, and `String`. It is expected that if you use `noLib` you will be including your own type definitions for these. 10 | -------------------------------------------------------------------------------- /docs/tsconfig/rewriteRelativeImportExtensions.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'rewriteRelativeImportExtensions' 3 | oneline: 'Rewrite `.ts`, `.tsx`, `.mts`, and `.cts` file extensions in relative import paths to their JavaScript equivalent in output files.' 4 | --- 5 | 6 | Rewrite `.ts`, `.tsx`, `.mts`, and `.cts` file extensions in relative import paths to their JavaScript equivalent in output files. 7 | 8 | For more information, see the [TypeScript 5.7 release notes](/docs/handbook/release-notes/typescript-5-7.html#path-rewriting-for-relative-paths). 9 | -------------------------------------------------------------------------------- /docs/tsconfig/extendedDiagnostics.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Extended Diagnostics' 3 | oneline: 'Output more detailed compiler performance information after building.' 4 | --- 5 | 6 | You can use this flag to discover where TypeScript is spending its time when compiling. 7 | This is a tool used for understanding the performance characteristics of your codebase overall. 8 | 9 | You can learn more about how to measure and understand the output in the performance [section of the wiki](https://github.com/microsoft/TypeScript/wiki/Performance). 10 | -------------------------------------------------------------------------------- /docs/tsconfig/noStrictGenericChecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Strict Generic Checks' 3 | oneline: 'Disable strict checking of generic signatures in function types.' 4 | --- 5 | 6 | TypeScript will unify type parameters when comparing two generic functions. 7 | 8 | ```ts twoslash 9 | // @errors: 2322 10 | 11 | type A = (x: T, y: U) => [T, U]; 12 | type B = (x: S, y: S) => [S, S]; 13 | 14 | function f(a: A, b: B) { 15 | b = a; // Ok 16 | a = b; // Error 17 | } 18 | ``` 19 | 20 | This flag can be used to remove that check. 21 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /docs/tsconfig/keyofStringsOnly.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Keyof Strings Only' 3 | oneline: 'Make keyof only return strings instead of string, numbers or symbols. Legacy option.' 4 | --- 5 | 6 | This flag changes the `keyof` type operator to return `string` instead of `string | number` when applied to a type with a string index signature. 7 | 8 | This flag is used to help people keep this behavior from [before TypeScript 2.9's release](/docs/handbook/release-notes/typescript-2-9.html#support-number-and-symbol-named-properties-with-keyof-and-mapped-types). 9 | -------------------------------------------------------------------------------- /docs/tsconfig/noEmit.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Emit' 3 | oneline: 'Disable emitting files from a compilation.' 4 | --- 5 | 6 | Do not emit compiler output files like JavaScript source code, source-maps or declarations. 7 | 8 | This makes room for another tool like [Babel](https://babeljs.io), or [swc](https://github.com/swc-project/swc) to handle converting the TypeScript file to a file which can run inside a JavaScript environment. 9 | 10 | You can then use TypeScript as a tool for providing editor integration, and as a source code type-checker. 11 | -------------------------------------------------------------------------------- /docs/tsconfig/noResolve.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Resolve' 3 | oneline: 'Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project.' 4 | --- 5 | 6 | By default, TypeScript will examine the initial set of files for `import` and ` 18) { 20 | verified: true; 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /docs/tsconfig/watchDirectory.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Watch Directory' 3 | oneline: 'Specify how directories are watched on systems that lack recursive file-watching functionality.' 4 | --- 5 | 6 | The strategy for how entire directory trees are watched under systems that lack recursive file-watching functionality. 7 | 8 | - `fixedPollingInterval`: Check every directory for changes several times a second at a fixed interval. 9 | - `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified directories will be checked less often. 10 | - `useFsEvents` (the default): Attempt to use the operating system/file system's native events for directory changes. 11 | -------------------------------------------------------------------------------- /docs/tsconfig/noFallthroughCasesInSwitch.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Fallthrough Cases In Switch' 3 | oneline: 'Enable error reporting for fallthrough cases in switch statements.' 4 | --- 5 | 6 | Report errors for fallthrough cases in switch statements. 7 | Ensures that any non-empty case inside a switch statement includes either `break`, `return`, or `throw`. 8 | This means you won't accidentally ship a case fallthrough bug. 9 | 10 | ```ts twoslash 11 | // @noFallthroughCasesInSwitch 12 | // @errors: 7029 13 | const a: number = 6; 14 | 15 | switch (a) { 16 | case 0: 17 | console.log('even'); 18 | case 1: 19 | console.log('odd'); 20 | break; 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/tsconfig/forceConsistentCasingInFileNames.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Force Consistent Casing In File Names' 3 | oneline: 'Ensure that casing is correct in imports.' 4 | --- 5 | 6 | TypeScript follows the case sensitivity rules of the file system it's running on. 7 | This can be problematic if some developers are working in a case-sensitive file system and others aren't. 8 | If a file attempts to import `fileManager.ts` by specifying `./FileManager.ts` the file will be found in a case-insensitive file system, but not on a case-sensitive file system. 9 | 10 | When this option is set, TypeScript will issue an error if a program tries to include a file by a casing different from the casing on disk. 11 | -------------------------------------------------------------------------------- /docs/tsconfig/strict.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strict' 3 | oneline: 'Enable all strict type-checking options.' 4 | --- 5 | 6 | The `strict` flag enables a wide range of type checking behavior that results in stronger guarantees of program correctness. 7 | Turning this on is equivalent to enabling all of the _strict mode family_ options, which are outlined below. 8 | You can then turn off individual strict mode family checks as needed. 9 | 10 | Future versions of TypeScript may introduce additional stricter checking under this flag, so upgrades of TypeScript might result in new type errors in your program. 11 | When appropriate and possible, a corresponding flag will be added to disable that behavior. 12 | -------------------------------------------------------------------------------- /docs/tsconfig/experimentalDecorators.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Experimental Decorators' 3 | oneline: 'Enable experimental support for TC39 stage 2 draft decorators.' 4 | --- 5 | 6 | Enables [experimental support for decorators](https://github.com/tc39/proposal-decorators), which is a version of decorators that predates the TC39 standardization process. 7 | 8 | Decorators are a language feature which hasn't yet been fully ratified into the JavaScript specification. 9 | This means that the implementation version in TypeScript may differ from the implementation in JavaScript when it it decided by TC39. 10 | 11 | You can find out more about decorator support in TypeScript in [the handbook](/docs/handbook/decorators.html). 12 | -------------------------------------------------------------------------------- /docs/tsconfig/useDefineForClassFields.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Use Define For Class Fields' 3 | oneline: 'Emit ECMAScript-standard-compliant class fields.' 4 | --- 5 | 6 | This flag is used as part of migrating to the upcoming standard version of class fields. TypeScript introduced class fields many years before it was ratified in TC39. The latest version of the upcoming specification has a different runtime behavior to TypeScript's implementation but the same syntax. 7 | 8 | This flag switches to the upcoming ECMA runtime behavior. 9 | 10 | You can read more about the transition in [the 3.7 release notes](/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier). 11 | -------------------------------------------------------------------------------- /docs/tsconfig/exclude.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Exclude' 3 | oneline: 'Filters results from the [`include`](#include) option.' 4 | --- 5 | 6 | Specifies an array of filenames or patterns that should be skipped when resolving [`include`](#include). 7 | 8 | **Important**: `exclude` _only_ changes which files are included as a result of the [`include`](#include) setting. 9 | A file specified by `exclude` can still become part of your codebase due to an `import` statement in your code, a `types` inclusion, a `/// ` directives) are all resolved relative to the location of the symbolic link file, rather than relative to the path that the symbolic link resolves to. 11 | -------------------------------------------------------------------------------- /docs/tsconfig/noImplicitAny.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Implicit Any' 3 | oneline: 'Enable error reporting for expressions and declarations with an implied `any` type.' 4 | --- 5 | 6 | In some cases where no type annotations are present, TypeScript will fall back to a type of `any` for a variable when it cannot infer the type. 7 | 8 | This can cause some errors to be missed, for example: 9 | 10 | ```ts twoslash 11 | // @noImplicitAny: false 12 | function fn(s) { 13 | // No error? 14 | console.log(s.subtr(3)); 15 | } 16 | fn(42); 17 | ``` 18 | 19 | Turning on `noImplicitAny` however TypeScript will issue an error whenever it would have inferred `any`: 20 | 21 | ```ts twoslash 22 | // @errors: 7006 23 | function fn(s) { 24 | console.log(s.subtr(3)); 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/tsconfig/suppressExcessPropertyErrors.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Suppress Excess Property Errors' 3 | oneline: 'Disable reporting of excess property errors during the creation of object literals.' 4 | --- 5 | 6 | This disables reporting of excess property errors, such as the one shown in the following example: 7 | 8 | ```ts twoslash 9 | // @errors: 2322 10 | type Point = { x: number; y: number }; 11 | const p: Point = { x: 1, y: 3, m: 10 }; 12 | ``` 13 | 14 | This flag was added to help people migrate to the stricter checking of new object literals in [TypeScript 1.6](/docs/handbook/release-notes/typescript-1-6.html#stricter-object-literal-assignment-checks). 15 | 16 | We don't recommend using this flag in a modern codebase, you can suppress one-off cases where you need it using `// @ts-ignore`. 17 | -------------------------------------------------------------------------------- /prompts/hows-my-tsconfig-score.md: -------------------------------------------------------------------------------- 1 | You will receive some feedback given about a tsconfig.json file. 2 | 3 | Your job is to score how positive the feedback is on a scale of 1 to 10, 10 being the best. 4 | 5 | Reply only with the score, no other text. 6 | 7 | - 10/10 - Extremely modern and up to date 8 | - 9/10 - Very modern and up to date 9 | - 8/10 - Modern and up to date 10 | - 7/10 - Somewhat modern and up to date 11 | - 6/10 - Somewhat outdated 12 | - 5/10 - Outdated 13 | - 4/10 - Very outdated 14 | - 3/10 - Extremely outdated 15 | - 2/10 - Unbelievably outdated 16 | - 1/10 - The absolute worst 17 | 18 | Format it like so, with an emoji next to the score: 19 | 20 | 10/10 🎉 21 | 9/10 🎉 22 | 8/10 🎉 23 | 7/10 🎉 24 | 6/10 🤔 25 | 5/10 🤔 26 | 4/10 😕 27 | 3/10 😕 28 | 2/10 😕 29 | 1/10 💀 30 | -------------------------------------------------------------------------------- /docs/tsconfig/noImplicitThis.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Implicit This' 3 | oneline: 'Enable error reporting when `this` is given the type `any`.' 4 | --- 5 | 6 | Raise error on 'this' expressions with an implied 'any' type. 7 | 8 | For example, the class below returns a function which tries to access `this.width` and `this.height` – but the context 9 | for `this` inside the function inside `getAreaFunction` is not the instance of the Rectangle. 10 | 11 | ```ts twoslash 12 | // @errors: 2683 13 | class Rectangle { 14 | width: number; 15 | height: number; 16 | 17 | constructor(width: number, height: number) { 18 | this.width = width; 19 | this.height = height; 20 | } 21 | 22 | getAreaFunction() { 23 | return function () { 24 | return this.width * this.height; 25 | }; 26 | } 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/tsconfig/watchFile.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Watch File' 3 | oneline: 'Specify how the TypeScript watch mode works.' 4 | --- 5 | 6 | The strategy for how individual files are watched. 7 | 8 | - `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. 9 | - `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. 10 | - `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. 11 | - `useFsEvents` (the default): Attempt to use the operating system/file system's native events for file changes. 12 | - `useFsEventsOnParentDirectory`: Attempt to use the operating system/file system's native events to listen for changes on a file's parent directory 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Base Options: */ 4 | "esModuleInterop": true, 5 | "skipLibCheck": true, 6 | "target": "es2022", 7 | "allowJs": true, 8 | "resolveJsonModule": true, 9 | "moduleDetection": "force", 10 | "isolatedModules": true, 11 | "verbatimModuleSyntax": true, 12 | "noImplicitAny": true, 13 | 14 | /* Strictness */ 15 | "strict": true, 16 | "noUncheckedIndexedAccess": true, 17 | "noImplicitOverride": true, 18 | 19 | /* If transpiling with TypeScript: */ 20 | "module": "NodeNext", 21 | "outDir": "dist", 22 | "rootDir": "src", 23 | "sourceMap": true, 24 | "rewriteRelativeImportExtensions": true, 25 | "erasableSyntaxOnly": true, 26 | "lib": ["ES2022"], 27 | 28 | /* AND if you're building for a library: */ 29 | "declaration": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docs/tsconfig/typeRoots.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Type Roots' 3 | oneline: 'Specify multiple folders that act like `./node_modules/@types`.' 4 | --- 5 | 6 | By default all _visible_ "`@types`" packages are included in your compilation. 7 | Packages in `node_modules/@types` of any enclosing folder are considered _visible_. 8 | For example, that means packages within `./node_modules/@types/`, `../node_modules/@types/`, `../../node_modules/@types/`, and so on. 9 | 10 | If `typeRoots` is specified, _only_ packages under `typeRoots` will be included. For example: 11 | 12 | ```json tsconfig 13 | { 14 | "compilerOptions": { 15 | "typeRoots": ["./typings", "./vendor/types"] 16 | } 17 | } 18 | ``` 19 | 20 | This config file will include _all_ packages under `./typings` and `./vendor/types`, and no packages from `./node_modules/@types`. 21 | All paths are relative to the `tsconfig.json`. 22 | -------------------------------------------------------------------------------- /docs/tsconfig/suppressImplicitAnyIndexErrors.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Suppress Implicit Any Index Errors' 3 | oneline: 'Suppress [`noImplicitAny`](#noImplicitAny) errors when indexing objects that lack index signatures.' 4 | --- 5 | 6 | Turning `suppressImplicitAnyIndexErrors` on suppresses reporting the error about implicit anys when indexing into objects, as shown in the following example: 7 | 8 | ```ts twoslash 9 | // @noImplicitAny: true 10 | // @suppressImplicitAnyIndexErrors: false 11 | // @strict: true 12 | // @errors: 7053 13 | const obj = { x: 10 }; 14 | console.log(obj['foo']); 15 | ``` 16 | 17 | Using `suppressImplicitAnyIndexErrors` is quite a drastic approach. It is recommended to use a `@ts-ignore` comment instead: 18 | 19 | ```ts twoslash 20 | // @noImplicitAny: true 21 | // @strict: true 22 | const obj = { x: 10 }; 23 | // @ts-ignore 24 | console.log(obj['foo']); 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/tsconfig/generateCpuProfile.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Generate CPU Profile' 3 | oneline: 'Emit a v8 CPU profile of the compiler run for debugging.' 4 | --- 5 | 6 | This option gives you the chance to have TypeScript emit a v8 CPU profile during the compiler run. The CPU profile can provide insight into why your builds may be slow. 7 | 8 | This option can only be used from the CLI via: `--generateCpuProfile tsc-output.cpuprofile`. 9 | 10 | ```sh 11 | npm run tsc --generateCpuProfile tsc-output.cpuprofile 12 | ``` 13 | 14 | This file can be opened in a chromium based browser like Chrome or Edge Developer in [the CPU profiler](https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution) section. 15 | You can learn more about understanding the compilers performance in the [TypeScript wiki section on performance](https://github.com/microsoft/TypeScript/wiki/Performance). 16 | -------------------------------------------------------------------------------- /docs/tsconfig/strictPropertyInitialization.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strict Property Initialization' 3 | oneline: 'Check for class properties that are declared but not set in the constructor.' 4 | --- 5 | 6 | When set to true, TypeScript will raise an error when a class property was declared but not set in the constructor. 7 | 8 | ```ts twoslash 9 | // @errors: 2564 10 | class UserAccount { 11 | name: string; 12 | accountType = 'user'; 13 | 14 | email: string; 15 | address: string | undefined; 16 | 17 | constructor(name: string) { 18 | this.name = name; 19 | // Note that this.email is not set 20 | } 21 | } 22 | ``` 23 | 24 | In the above case: 25 | 26 | - `this.name` is set specifically. 27 | - `this.accountType` is set by default. 28 | - `this.email` is not set and raises an error. 29 | - `this.address` is declared as potentially `undefined` which means it does not have to be set. 30 | -------------------------------------------------------------------------------- /docs/tsconfig/baseUrl.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Base URL' 3 | oneline: 'Specify the base directory to resolve bare specifier module names.' 4 | --- 5 | 6 | Sets a base directory from which to resolve bare specifier module names. For example, in the directory structure: 7 | 8 | ``` 9 | project 10 | ├── ex.ts 11 | ├── hello 12 | │ └── world.ts 13 | └── tsconfig.json 14 | ``` 15 | 16 | With `"baseUrl": "./"`, TypeScript will look for files starting at the same folder as the `tsconfig.json`: 17 | 18 | ```ts 19 | import { helloWorld } from 'hello/world'; 20 | 21 | console.log(helloWorld); 22 | ``` 23 | 24 | This resolution has higher priority than lookups from `node_modules`. 25 | 26 | This feature was designed for use in conjunction with AMD module loaders in the browser, and is not recommended in any other context. As of TypeScript 4.1, `baseUrl` is no longer required to be set when using [`paths`](#paths). 27 | -------------------------------------------------------------------------------- /docs/tsconfig/moduleSuffixes.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Module Suffixes' 3 | oneline: 'List of file name suffixes to search when resolving a module.' 4 | --- 5 | 6 | Provides a way to override the default list of file name suffixes to search when resolving a module. 7 | 8 | ```json tsconfig 9 | { 10 | "compilerOptions": { 11 | "moduleSuffixes": [".ios", ".native", ""] 12 | } 13 | } 14 | ``` 15 | 16 | Given the above configuration, an import like the following: 17 | 18 | ```ts 19 | import * as foo from './foo'; 20 | ``` 21 | 22 | TypeScript will look for the relative files `./foo.ios.ts`, `./foo.native.ts`, and finally `./foo.ts`. 23 | 24 | Note the empty string `""` in [`moduleSuffixes`](#moduleSuffixes) which is necessary for TypeScript to also look-up `./foo.ts`. 25 | 26 | This feature can be useful for React Native projects where each target platform can use a separate tsconfig.json with differing `moduleSuffixes`. 27 | -------------------------------------------------------------------------------- /docs/tsconfig/moduleDetection.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Module Detection' 3 | oneline: 'Specify what method is used to detect whether a file is a script or a module.' 4 | --- 5 | 6 | This setting controls how TypeScript determines whether a file is a 7 | [script or a module](/docs/handbook/modules/theory.html#scripts-and-modules-in-javascript). 8 | 9 | There are three choices: 10 | 11 | - `"auto"` (default) - TypeScript will not only look for import and export statements, but it will also check whether the `"type"` field in a `package.json` is set to `"module"` when running with [`module`](#module): `nodenext` or `node16`, and check whether the current file is a JSX file when running under [`jsx`](#jsx): `react-jsx`. 12 | 13 | - `"legacy"` - The same behavior as 4.6 and prior, usings import and export statements to determine whether a file is a module. 14 | 15 | - `"force"` - Ensures that every non-declaration file is treated as a module. 16 | -------------------------------------------------------------------------------- /docs/tsconfig/useUnknownInCatchVariables.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Use Unknown In Catch Variables' 3 | oneline: 'Default catch clause variables as `unknown` instead of `any`.' 4 | --- 5 | 6 | In TypeScript 4.0, support was added to allow changing the type of the variable in a catch clause from `any` to `unknown`. Allowing for code like: 7 | 8 | ```ts twoslash 9 | // @useUnknownInCatchVariables 10 | try { 11 | // ... 12 | } catch (err: unknown) { 13 | // We have to verify err is an 14 | // error before using it as one. 15 | if (err instanceof Error) { 16 | console.log(err.message); 17 | } 18 | } 19 | ``` 20 | 21 | This pattern ensures that error handling code becomes more comprehensive because you cannot guarantee that the object being thrown _is_ a Error subclass ahead of time. With the flag `useUnknownInCatchVariables` enabled, then you do not need the additional syntax (`: unknown`) nor a linter rule to try enforce this behavior. 22 | -------------------------------------------------------------------------------- /docs/tsconfig/composite.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Composite' 3 | oneline: 'Enable constraints that allow a TypeScript project to be used with project references.' 4 | --- 5 | 6 | The `composite` option enforces certain constraints which make it possible for build tools (including TypeScript 7 | itself, under `--build` mode) to quickly determine if a project has been built yet. 8 | 9 | When this setting is on: 10 | 11 | - The [`rootDir`](#rootDir) setting, if not explicitly set, defaults to the directory containing the `tsconfig.json` file. 12 | 13 | - All implementation files must be matched by an [`include`](#include) pattern or listed in the [`files`](#files) array. If this constraint is violated, `tsc` will inform you which files weren't specified. 14 | 15 | - [`declaration`](#declaration) defaults to `true` 16 | 17 | You can find documentation on TypeScript projects in [the handbook](https://www.typescriptlang.org/docs/handbook/project-references.html). 18 | -------------------------------------------------------------------------------- /docs/tsconfig/outDir.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Out Dir' 3 | oneline: 'Specify an output folder for all emitted files.' 4 | --- 5 | 6 | If specified, `.js` (as well as `.d.ts`, `.js.map`, etc.) files will be emitted into this directory. 7 | The directory structure of the original source files is preserved; see [`rootDir`](#rootDir) if the computed root is not what you intended. 8 | 9 | If not specified, `.js` files will be emitted in the same directory as the `.ts` files they were generated from: 10 | 11 | ```sh 12 | $ tsc 13 | 14 | example 15 | ├── index.js 16 | └── index.ts 17 | ``` 18 | 19 | With a `tsconfig.json` like this: 20 | 21 | ```json tsconfig 22 | { 23 | "compilerOptions": { 24 | "outDir": "dist" 25 | } 26 | } 27 | ``` 28 | 29 | Running `tsc` with these settings moves the files into the specified `dist` folder: 30 | 31 | ```sh 32 | $ tsc 33 | 34 | example 35 | ├── dist 36 | │ └── index.js 37 | ├── index.ts 38 | └── tsconfig.json 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/tsconfig/preserveValueImports.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Preserve Value Imports' 3 | oneline: 'Preserve unused imported values in the JavaScript output that would otherwise be removed.' 4 | --- 5 | 6 | Deprecated in favor of [`verbatimModuleSyntax`](#verbatimModuleSyntax). 7 | 8 | There are some cases where TypeScript can't detect that you're using an import. For example, take the following code: 9 | 10 | ```ts 11 | import { Animal } from './animal.js'; 12 | 13 | eval('console.log(new Animal().isDangerous())'); 14 | ``` 15 | 16 | or code using 'Compiles to HTML' languages like Svelte or Vue. `preserveValueImports` will prevent TypeScript from removing the import, even if it appears unused. 17 | 18 | When combined with [`isolatedModules`](#isolatedModules): imported types _must_ be marked as type-only because compilers that process single files at a time have no way of knowing whether imports are values that appear unused, or a type that must be removed in order to avoid a runtime crash. 19 | -------------------------------------------------------------------------------- /docs/tsconfig/removeComments.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Remove Comments' 3 | oneline: 'Disable emitting comments.' 4 | --- 5 | 6 | Strips all comments from TypeScript files when converting into JavaScript. Defaults to `false`. 7 | 8 | For example, this is a TypeScript file which has a JSDoc comment: 9 | 10 | ```ts 11 | /** The translation of 'Hello world' into Portuguese */ 12 | export const helloWorldPTBR = 'Olá Mundo'; 13 | ``` 14 | 15 | When `removeComments` is set to `true`: 16 | 17 | ```ts twoslash 18 | // @showEmit 19 | // @removeComments: true 20 | /** The translation of 'Hello world' into Portuguese */ 21 | export const helloWorldPTBR = 'Olá Mundo'; 22 | ``` 23 | 24 | Without setting `removeComments` or having it as `false`: 25 | 26 | ```ts twoslash 27 | // @showEmit 28 | // @removeComments: false 29 | /** The translation of 'Hello world' into Portuguese */ 30 | export const helloWorldPTBR = 'Olá Mundo'; 31 | ``` 32 | 33 | This means that your comments will show up in the JavaScript code. 34 | -------------------------------------------------------------------------------- /docs/tsconfig/strictBindCallApply.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strict Bind Call Apply' 3 | oneline: 'Check that the arguments for `bind`, `call`, and `apply` methods match the original function.' 4 | --- 5 | 6 | When set, TypeScript will check that the built-in methods of functions `call`, `bind`, and `apply` are invoked with correct argument for the underlying function: 7 | 8 | ```ts twoslash 9 | // @strictBindCallApply: true 10 | // @errors: 2345 11 | 12 | // With strictBindCallApply on 13 | function fn(x: string) { 14 | return parseInt(x); 15 | } 16 | 17 | const n1 = fn.call(undefined, '10'); 18 | 19 | const n2 = fn.call(undefined, false); 20 | ``` 21 | 22 | Otherwise, these functions accept any arguments and will return `any`: 23 | 24 | ```ts twoslash 25 | // @strictBindCallApply: false 26 | 27 | // With strictBindCallApply off 28 | function fn(x: string) { 29 | return parseInt(x); 30 | } 31 | 32 | // Note: No error; return type is 'any' 33 | const n = fn.call(undefined, false); 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/tsconfig/importsNotUsedAsValues.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Imports Not Used As Values' 3 | oneline: 'Specify emit/checking behavior for imports that are only used for types.' 4 | --- 5 | 6 | Deprecated in favor of [`verbatimModuleSyntax`](#verbatimModuleSyntax). 7 | 8 | This flag controls how `import` works, there are 3 different options: 9 | 10 | - `remove`: The default behavior of dropping `import` statements which only reference types. 11 | 12 | - `preserve`: Preserves all `import` statements whose values or types are never used. This can cause imports/side-effects to be preserved. 13 | 14 | - `error`: This preserves all imports (the same as the preserve option), but will error when a value import is only used as a type. This might be useful if you want to ensure no values are being accidentally imported, but still make side-effect imports explicit. 15 | 16 | This flag works because you can use `import type` to explicitly create an `import` statement which should never be emitted into JavaScript. 17 | -------------------------------------------------------------------------------- /docs/tsconfig/allowUnreachableCode.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Allow Unreachable Code' 3 | oneline: 'Disable error reporting for unreachable code.' 4 | --- 5 | 6 | When: 7 | 8 | - `undefined` (default) provide suggestions as warnings to editors 9 | - `true` unreachable code is ignored 10 | - `false` raises compiler errors about unreachable code 11 | 12 | These warnings are only about code which is provably unreachable due to the use of JavaScript syntax, for example: 13 | 14 | ```ts 15 | function fn(n: number) { 16 | if (n > 5) { 17 | return true; 18 | } else { 19 | return false; 20 | } 21 | return true; 22 | } 23 | ``` 24 | 25 | With `"allowUnreachableCode": false`: 26 | 27 | ```ts twoslash 28 | // @errors: 7027 29 | // @allowUnreachableCode: false 30 | function fn(n: number) { 31 | if (n > 5) { 32 | return true; 33 | } else { 34 | return false; 35 | } 36 | return true; 37 | } 38 | ``` 39 | 40 | This does not affect errors on the basis of code which _appears_ to be unreachable due to type analysis. 41 | -------------------------------------------------------------------------------- /docs/tsconfig/locale.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Locale' 3 | oneline: 'Set the language of the messaging from TypeScript. This does not affect emit.' 4 | --- 5 | 6 | TypeScript supports a number of languages, however this cannot be set via the `tsconfig.json`, only 7 | via the host environment or the CLI flag `--locale`. E.g. `tsc --locale ru`. 8 | 9 | ### Locales supported as of TypeScript 3.7 10 | 11 | | Name | Locale | 12 | | --------------------- | ------- | 13 | | Brazilian Portuguese | `pr-BR` | 14 | | Chinese (Simplified) | `zh-TW` | 15 | | Chinese (Traditional) | `zh-CN` | 16 | | Czech | `cs-CZ` | 17 | | English (US) | `en-US` | 18 | | French | `fr-FR` | 19 | | German | `de-DE` | 20 | | Italian | `it-IT` | 21 | | Japanese | `ja-JP` | 22 | | Korean | `ko-KR` | 23 | | Polish | `pl-PL` | 24 | | Russian | `ru-RU` | 25 | | Spanish | `es-ES` | 26 | | Turkish | `tr-TR` | 27 | -------------------------------------------------------------------------------- /docs/tsconfig/fallbackPolling.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Fallback Polling' 3 | oneline: 'Specify what approach the watcher should use if the system runs out of native file watchers.' 4 | --- 5 | 6 | When using file system events, this option specifies the polling strategy that gets used when the system runs out of native file watchers and/or doesn't support native file watchers. 7 | 8 | - `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. 9 | - `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. 10 | - `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. 11 | - `synchronousWatchDirectory`: Disable deferred watching on directories. Deferred watching is useful when lots of file changes might occur at once (e.g. a change in `node_modules` from running `npm install`), but you might want to disable it with this flag for some less-common setups. 12 | -------------------------------------------------------------------------------- /docs/tsconfig/listEmittedFiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'List Emitted Files' 3 | oneline: 'Print the names of emitted files after a compilation.' 4 | --- 5 | 6 | Print names of generated files part of the compilation to the terminal. 7 | 8 | This flag is useful in two cases: 9 | 10 | - You want to transpile TypeScript as a part of a build chain in the terminal where the filenames are processed in the next command. 11 | - You are not sure that TypeScript has included a file you expected, as a part of debugging the [file inclusion settings](#Project_Files_0). 12 | 13 | For example: 14 | 15 | ``` 16 | example 17 | ├── index.ts 18 | ├── package.json 19 | └── tsconfig.json 20 | ``` 21 | 22 | With: 23 | 24 | ```json tsconfig 25 | { 26 | "compilerOptions": { 27 | "declaration": true, 28 | "listEmittedFiles": true 29 | } 30 | } 31 | ``` 32 | 33 | Would echo paths like: 34 | 35 | ``` 36 | $ npm run tsc 37 | 38 | path/to/example/index.js 39 | path/to/example/index.d.ts 40 | ``` 41 | 42 | Normally, TypeScript would return silently on success. 43 | -------------------------------------------------------------------------------- /docs/tsconfig/tsBuildInfoFile.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'TS Build Info File' 3 | oneline: 'The file to store `.tsbuildinfo` incremental build information in.' 4 | --- 5 | 6 | This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster 7 | building of larger TypeScript codebases. You can read more about composite projects [in the handbook](/docs/handbook/project-references.html). 8 | 9 | The default depends on a combination of other settings: 10 | 11 | - If `outFile` is set, the default is `.tsbuildinfo`. 12 | - If `rootDir` and `outDir` are set, then the file is `//.tsbuildinfo` 13 | For example, if `rootDir` is `src`, `outDir` is `dest`, and the config is 14 | `./tsconfig.json`, then the default is `./tsconfig.tsbuildinfo` 15 | as the relative path from `src/` to `./tsconfig.json` is `../`. 16 | - If `outDir` is set, then the default is `/.tsbuildInfo` 17 | - Otherwise, the default is `.tsbuildInfo` 18 | -------------------------------------------------------------------------------- /docs/tsconfig/noEmitHelpers.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Emit Helpers' 3 | oneline: 'Disable generating custom helper functions like `__extends` in compiled output.' 4 | --- 5 | 6 | Instead of importing helpers with [`importHelpers`](#importHelpers), you can provide implementations in the global scope for the helpers you use and completely turn off emitting of helper functions. 7 | 8 | For example, using this `async` function in ES5 requires a `await`-like function and `generator`-like function to run: 9 | 10 | ```ts twoslash 11 | const getAPI = async (url: string) => { 12 | // Get API 13 | return {}; 14 | }; 15 | ``` 16 | 17 | Which creates quite a lot of JavaScript: 18 | 19 | ```ts twoslash 20 | // @showEmit 21 | // @target: ES5 22 | const getAPI = async (url: string) => { 23 | // Get API 24 | return {}; 25 | }; 26 | ``` 27 | 28 | Which can be switched out with your own globals via this flag: 29 | 30 | ```ts twoslash 31 | // @showEmit 32 | // @target: ES5 33 | // @noEmitHelpers 34 | const getAPI = async (url: string) => { 35 | // Get API 36 | return {}; 37 | }; 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/tsconfig/listFiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'List Files' 3 | oneline: 'Print all of the files read during the compilation.' 4 | --- 5 | 6 | Print names of files part of the compilation. This is useful when you are not sure that TypeScript has 7 | included a file you expected. 8 | 9 | For example: 10 | 11 | ``` 12 | example 13 | ├── index.ts 14 | ├── package.json 15 | └── tsconfig.json 16 | ``` 17 | 18 | With: 19 | 20 | ```json tsconfig 21 | { 22 | "compilerOptions": { 23 | "listFiles": true 24 | } 25 | } 26 | ``` 27 | 28 | Would echo paths like: 29 | 30 | ``` 31 | $ npm run tsc 32 | path/to/example/node_modules/typescript/lib/lib.d.ts 33 | path/to/example/node_modules/typescript/lib/lib.es5.d.ts 34 | path/to/example/node_modules/typescript/lib/lib.dom.d.ts 35 | path/to/example/node_modules/typescript/lib/lib.webworker.importscripts.d.ts 36 | path/to/example/node_modules/typescript/lib/lib.scripthost.d.ts 37 | path/to/example/index.ts 38 | ``` 39 | 40 | Note if using TypeScript 4.2, prefer [`explainFiles`](#explainFiles) which offers an explanation of why a file was added too. 41 | -------------------------------------------------------------------------------- /src/model.ts: -------------------------------------------------------------------------------- 1 | import { anthropic } from '@ai-sdk/anthropic'; 2 | import type { Config } from './config.ts'; 3 | import type { LanguageModelV1 } from 'ai'; 4 | import { openai } from '@ai-sdk/openai'; 5 | import { google } from '@ai-sdk/google'; 6 | 7 | export const getModel = ( 8 | config: Config, 9 | ): { 10 | thoughts: LanguageModelV1; 11 | score: LanguageModelV1; 12 | } => { 13 | switch (config.provider) { 14 | case 'anthropic': 15 | process.env.ANTHROPIC_API_KEY = config.apiKey; 16 | return { 17 | thoughts: anthropic('claude-4-sonnet-20250514'), 18 | score: anthropic('claude-3-5-haiku-latest'), 19 | }; 20 | case 'openai': 21 | process.env.OPENAI_API_KEY = config.apiKey; 22 | return { 23 | thoughts: openai('gpt-4o'), 24 | score: openai('gpt-4o-mini'), 25 | }; 26 | case 'google': 27 | process.env.GOOGLE_GENERATIVE_AI_API_KEY = config.apiKey; 28 | return { 29 | thoughts: google('gemini-2.5-flash-preview-04-17'), 30 | score: google('gemini-2.5-flash-preview-04-17'), 31 | }; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /docs/tsconfig/inlineSourceMap.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Inline Source Map' 3 | oneline: 'Include sourcemap files inside the emitted JavaScript.' 4 | --- 5 | 6 | When set, instead of writing out a `.js.map` file to provide source maps, TypeScript will embed the source map content in the `.js` files. 7 | Although this results in larger JS files, it can be convenient in some scenarios. 8 | For example, you might want to debug JS files on a webserver that doesn't allow `.map` files to be served. 9 | 10 | Mutually exclusive with [`sourceMap`](#sourceMap). 11 | 12 | For example, with this TypeScript: 13 | 14 | ```ts 15 | const helloWorld = 'hi'; 16 | console.log(helloWorld); 17 | ``` 18 | 19 | Converts to this JavaScript: 20 | 21 | ```ts twoslash 22 | // @showEmit 23 | const helloWorld = 'hi'; 24 | console.log(helloWorld); 25 | ``` 26 | 27 | Then enable building it with `inlineSourceMap` enabled there is a comment at the bottom of the file which includes 28 | a source-map for the file. 29 | 30 | ```ts twoslash 31 | // @inlineSourceMap 32 | // @showEmit 33 | const helloWorld = 'hi'; 34 | console.log(helloWorld); 35 | ``` 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Matt Pocock 2025 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/tsconfig/typeAcquisition.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Type Acquisition' 3 | oneline: 'Specify options for automatic acquisition of declaration files.' 4 | --- 5 | 6 | When you have a JavaScript project in your editor, TypeScript will provide types for your `node_modules` automatically using the DefinitelyTyped set of `@types` definitions. 7 | This is called automatic type acquisition, and you can customize it using the `typeAcquisition` object in your configuration. 8 | 9 | If you would like to disable or customize this feature, create a `jsconfig.json` in the root of your project: 10 | 11 | ```json 12 | { 13 | "typeAcquisition": { 14 | "enable": false 15 | } 16 | } 17 | ``` 18 | 19 | If you have a specific module which should be included (but isn't in `node_modules`): 20 | 21 | ```json 22 | { 23 | "typeAcquisition": { 24 | "include": ["jest"] 25 | } 26 | } 27 | ``` 28 | 29 | If a module should not be automatically acquired, for example if the library is available in your `node_modules` but your team has agreed to not use it: 30 | 31 | ```json 32 | { 33 | "typeAcquisition": { 34 | "exclude": ["jquery"] 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/tsconfig/declaration.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Declaration' 3 | oneline: 'Generate .d.ts files from TypeScript and JavaScript files in your project.' 4 | --- 5 | 6 | Generate `.d.ts` files for every TypeScript or JavaScript file inside your project. 7 | These `.d.ts` files are type definition files which describe the external API of your module. 8 | With `.d.ts` files, tools like TypeScript can provide intellisense and accurate types for un-typed code. 9 | 10 | When `declaration` is set to `true`, running the compiler with this TypeScript code: 11 | 12 | ```ts twoslash 13 | export let helloWorld = 'hi'; 14 | ``` 15 | 16 | Will generate an `index.js` file like this: 17 | 18 | ```ts twoslash 19 | // @showEmit 20 | export let helloWorld = 'hi'; 21 | ``` 22 | 23 | With a corresponding `helloWorld.d.ts`: 24 | 25 | ```ts twoslash 26 | // @showEmittedFile: index.d.ts 27 | // @showEmit 28 | // @declaration 29 | export let helloWorld = 'hi'; 30 | ``` 31 | 32 | When working with `.d.ts` files for JavaScript files you may want to use [`emitDeclarationOnly`](#emitDeclarationOnly) or use [`outDir`](#outDir) to ensure that the JavaScript files are not overwritten. 33 | -------------------------------------------------------------------------------- /docs/tsconfig/resolveJsonModule.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Resolve JSON Module' 3 | oneline: 'Enable importing .json files.' 4 | --- 5 | 6 | Allows importing modules with a `.json` extension, which is a common practice in node projects. This includes 7 | generating a type for the `import` based on the static JSON shape. 8 | 9 | TypeScript does not support resolving JSON files by default: 10 | 11 | ```ts twoslash 12 | // @errors: 2732 13 | // @filename: settings.json 14 | { 15 | "repo": "TypeScript", 16 | "dry": false, 17 | "debug": false 18 | } 19 | // @filename: index.ts 20 | import settings from "./settings.json"; 21 | 22 | settings.debug === true; 23 | settings.dry === 2; 24 | ``` 25 | 26 | Enabling the option allows importing JSON, and validating the types in that JSON file. 27 | 28 | ```ts twoslash 29 | // @errors: 2367 30 | // @resolveJsonModule 31 | // @module: commonjs 32 | // @moduleResolution: node 33 | // @filename: settings.json 34 | { 35 | "repo": "TypeScript", 36 | "dry": false, 37 | "debug": false 38 | } 39 | // @filename: index.ts 40 | import settings from "./settings.json"; 41 | 42 | settings.debug === true; 43 | settings.dry === 2; 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/tsconfig/libReplacement.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Lib Replacement' 3 | oneline: 'Enable substitution of default `lib` files with custom ones.' 4 | --- 5 | 6 | TypeScript 4.5 introduced the possibility of substituting the default `lib` files with custom ones. 7 | All built-in library files would first try to be resolved from packages named `@typescript/lib-*`. 8 | For example, you could lock your `dom` libraries onto a specific version of [the `@types/web` package](https://www.npmjs.com/package/@types/web?activeTab=readme) with the following `package.json`: 9 | 10 | ```json 11 | { 12 | "devDependencies": { 13 | "@typescript/lib-dom": "npm:@types/web@0.0.199" 14 | } 15 | } 16 | ``` 17 | 18 | When installed, a package called `@typescript/lib-dom` should exist, and TypeScript would always look there when searching for `lib.dom.d.ts`. 19 | 20 | The `--libReplacement` flag allows you to disable this behavior. 21 | If you're not using any `@typescript/lib-*` packages, you can now disable those package lookups with `--libReplacement false`. 22 | In the future, `--libReplacement false` may become the default, so if you currently rely on the behavior you should consider explicitly enabling it with `--libReplacement true`. 23 | -------------------------------------------------------------------------------- /docs/tsconfig/checkJs.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Check JS' 3 | oneline: 'Enable error reporting in type-checked JavaScript files.' 4 | --- 5 | 6 | Works in tandem with [`allowJs`](#allowJs). When `checkJs` is enabled then errors are reported in JavaScript files. This is 7 | the equivalent of including `// @ts-check` at the top of all JavaScript files which are included in your project. 8 | 9 | For example, this is incorrect JavaScript according to the `parseFloat` type definition which comes with TypeScript: 10 | 11 | ```js 12 | // parseFloat only takes a string 13 | module.exports.pi = parseFloat(3.142); 14 | ``` 15 | 16 | When imported into a TypeScript module: 17 | 18 | ```ts twoslash 19 | // @allowJs 20 | // @filename: constants.js 21 | module.exports.pi = parseFloat(3.142); 22 | 23 | // @filename: index.ts 24 | import { pi } from './constants'; 25 | console.log(pi); 26 | ``` 27 | 28 | You will not get any errors. However, if you turn on `checkJs` then you will get error messages from the JavaScript file. 29 | 30 | ```ts twoslash 31 | // @errors: 2345 32 | // @allowjs: true 33 | // @checkjs: true 34 | // @filename: constants.js 35 | module.exports.pi = parseFloat(3.142); 36 | 37 | // @filename: index.ts 38 | import { pi } from './constants'; 39 | console.log(pi); 40 | ``` 41 | -------------------------------------------------------------------------------- /docs/tsconfig/inlineSources.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Inline Sources' 3 | oneline: 'Include source code in the sourcemaps inside the emitted JavaScript.' 4 | --- 5 | 6 | When set, TypeScript will include the original content of the `.ts` file as an embedded string in the source map (using the source map's `sourcesContent` property). 7 | This is often useful in the same cases as [`inlineSourceMap`](#inlineSourceMap). 8 | 9 | Requires either [`sourceMap`](#sourceMap) or [`inlineSourceMap`](#inlineSourceMap) to be set. 10 | 11 | For example, with this TypeScript: 12 | 13 | ```ts twoslash 14 | const helloWorld = 'hi'; 15 | console.log(helloWorld); 16 | ``` 17 | 18 | By default converts to this JavaScript: 19 | 20 | ```ts twoslash 21 | // @showEmit 22 | const helloWorld = 'hi'; 23 | console.log(helloWorld); 24 | ``` 25 | 26 | Then enable building it with `inlineSources` and [`inlineSourceMap`](#inlineSourceMap) enabled there is a comment at the bottom of the file which includes 27 | a source-map for the file. 28 | Note that the end is different from the example in [`inlineSourceMap`](#inlineSourceMap) because the source-map now contains the original source code also. 29 | 30 | ```ts twoslash 31 | // @inlineSources 32 | // @inlineSourceMap 33 | // @showEmit 34 | const helloWorld = 'hi'; 35 | console.log(helloWorld); 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/tsconfig/sourceMap.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Source Map' 3 | oneline: 'Create source map files for emitted JavaScript files.' 4 | --- 5 | 6 | Enables the generation of [sourcemap files](https://developer.mozilla.org/docs/Tools/Debugger/How_to/Use_a_source_map). 7 | These files allow debuggers and other tools to display the original TypeScript source code when actually working with the emitted JavaScript files. 8 | Source map files are emitted as `.js.map` (or `.jsx.map`) files next to the corresponding `.js` output file. 9 | 10 | The `.js` files will in turn contain a sourcemap comment to indicate where the files are to external tools, for example: 11 | 12 | ```ts 13 | // helloWorld.ts 14 | export declare const helloWorld = 'hi'; 15 | ``` 16 | 17 | Compiling with `sourceMap` set to `true` creates the following JavaScript file: 18 | 19 | ```js 20 | // helloWorld.js 21 | 'use strict'; 22 | Object.defineProperty(exports, '__esModule', { value: true }); 23 | exports.helloWorld = 'hi'; 24 | //# sourceMappingURL=// helloWorld.js.map 25 | ``` 26 | 27 | And this also generates this json map: 28 | 29 | ```json 30 | // helloWorld.js.map 31 | { 32 | "version": 3, 33 | "file": "ex.js", 34 | "sourceRoot": "", 35 | "sources": ["../ex.ts"], 36 | "names": [], 37 | "mappings": ";;AAAa,QAAA,UAAU,GAAG,IAAI,CAAA" 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/tsconfig/plugins.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Plugins' 3 | oneline: 'Specify a list of language service plugins to include.' 4 | --- 5 | 6 | List of language service plugins to run inside the editor. 7 | 8 | Language service plugins are a way to provide additional information to a user based on existing TypeScript files. They can enhance existing messages between TypeScript and an editor, or to provide their own error messages. 9 | 10 | For example: 11 | 12 | - [ts-sql-plugin](https://github.com/xialvjun/ts-sql-plugin#readme) — Adds SQL linting with a template strings SQL builder. 13 | - [typescript-styled-plugin](https://github.com/Microsoft/typescript-styled-plugin) — Provides CSS linting inside template strings . 14 | - [typescript-eslint-language-service](https://github.com/Quramy/typescript-eslint-language-service) — Provides eslint error messaging and fix-its inside the compiler's output. 15 | - [ts-graphql-plugin](https://github.com/Quramy/ts-graphql-plugin) — Provides validation and auto-completion inside GraphQL query template strings. 16 | 17 | VS Code has the ability for a extension to [automatically include language service plugins](https://code.visualstudio.com/api/references/contribution-points#contributes.typescriptServerPlugins), and so you may have some running in your editor without needing to define them in your `tsconfig.json`. 18 | -------------------------------------------------------------------------------- /docs/tsconfig/moduleResolution.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Module Resolution' 3 | oneline: 'Specify how TypeScript looks up a file from a given module specifier.' 4 | --- 5 | 6 | Specify the module resolution strategy: 7 | 8 | - `'node16'` or `'nodenext'` for modern versions of Node.js. Node.js v12 and later supports both ECMAScript imports and CommonJS `require`, which resolve using different algorithms. These `moduleResolution` values, when combined with the corresponding [`module`](#module) values, picks the right algorithm for each resolution based on whether Node.js will see an `import` or `require` in the output JavaScript code. 9 | - `'node10'` (previously called `'node'`) for Node.js versions older than v10, which only support CommonJS `require`. You probably won't need to use `node10` in modern code. 10 | - `'bundler'` for use with bundlers. Like `node16` and `nodenext`, this mode supports package.json `"imports"` and `"exports"`, but unlike the Node.js resolution modes, `bundler` never requires file extensions on relative paths in imports. 11 | - `'classic'` was used in TypeScript before the release of 1.6. `classic` should not be used. 12 | 13 | There are reference pages explaining the [theory behind TypeScript’s module resolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) and the [details of each option](/docs/handbook/modules/reference.html#the-moduleresolution-compiler-option). 14 | -------------------------------------------------------------------------------- /docs/tsconfig/allowJs.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Allow JS' 3 | oneline: 'Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files.' 4 | --- 5 | 6 | Allow JavaScript files to be imported inside your project, instead of just `.ts` and `.tsx` files. For example, this JS file: 7 | 8 | ```js twoslash 9 | // @filename: card.js 10 | export const defaultCardDeck = 'Heart'; 11 | ``` 12 | 13 | When imported into a TypeScript file will raise an error: 14 | 15 | ```ts twoslash 16 | // @errors: 2307 17 | // @filename: card.js 18 | module.exports.defaultCardDeck = 'Heart'; 19 | // ---cut--- 20 | // @filename: index.ts 21 | import { defaultCardDeck } from './card'; 22 | 23 | console.log(defaultCardDeck); 24 | ``` 25 | 26 | Imports fine with `allowJs` enabled: 27 | 28 | ```ts twoslash 29 | // @filename: card.js 30 | module.exports.defaultCardDeck = 'Heart'; 31 | // ---cut--- 32 | // @allowJs 33 | // @filename: index.ts 34 | import { defaultCardDeck } from './card'; 35 | 36 | console.log(defaultCardDeck); 37 | ``` 38 | 39 | This flag can be used as a way to incrementally add TypeScript files into JS projects by allowing the `.ts` and `.tsx` files to live along-side existing JavaScript files. 40 | 41 | It can also be used along-side [`declaration`](#declaration) and [`emitDeclarationOnly`](#emitDeclarationOnly) to [create declarations for JS files](/docs/handbook/declaration-files/dts-from-js.html). 42 | -------------------------------------------------------------------------------- /docs/tsconfig/target.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Target' 3 | oneline: 'Set the JavaScript language version for emitted JavaScript and include compatible library declarations.' 4 | --- 5 | 6 | Modern browsers support all ES6 features, so `ES6` is a good choice. 7 | You might choose to set a lower target if your code is deployed to older environments, or a higher target if your code is guaranteed to run in newer environments. 8 | 9 | The `target` setting changes which JS features are downleveled and which are left intact. 10 | For example, an arrow function `() => this` will be turned into an equivalent `function` expression if `target` is ES5 or lower. 11 | 12 | Changing `target` also changes the default value of [`lib`](#lib). 13 | You may "mix and match" `target` and `lib` settings as desired, but you could just set `target` for convenience. 14 | 15 | For developer platforms like Node there are baselines for the `target`, depending on the type of platform and its version. You can find a set of community organized TSConfigs at [tsconfig/bases](https://github.com/tsconfig/bases#centralized-recommendations-for-tsconfig-bases), which has configurations for common platforms and their versions. 16 | 17 | The special `ESNext` value refers to the highest version your version of TypeScript supports. 18 | This setting should be used with caution, since it doesn't mean the same thing between different TypeScript versions and can make upgrades less predictable. 19 | -------------------------------------------------------------------------------- /docs/tsconfig/noErrorTruncation.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Error Truncation' 3 | oneline: 'Disable truncating types in error messages.' 4 | --- 5 | 6 | Do not truncate error messages. 7 | 8 | With `false`, the default. 9 | 10 | ```ts twoslash 11 | // @errors: 2322 2454 12 | var x: { 13 | propertyWithAnExceedinglyLongName1: string; 14 | propertyWithAnExceedinglyLongName2: string; 15 | propertyWithAnExceedinglyLongName3: string; 16 | propertyWithAnExceedinglyLongName4: string; 17 | propertyWithAnExceedinglyLongName5: string; 18 | propertyWithAnExceedinglyLongName6: string; 19 | propertyWithAnExceedinglyLongName7: string; 20 | propertyWithAnExceedinglyLongName8: string; 21 | }; 22 | 23 | // String representation of type of 'x' should be truncated in error message 24 | var s: string = x; 25 | ``` 26 | 27 | With `true` 28 | 29 | ```ts twoslash 30 | // @errors: 2322 2454 31 | // @noErrorTruncation: true 32 | var x: { 33 | propertyWithAnExceedinglyLongName1: string; 34 | propertyWithAnExceedinglyLongName2: string; 35 | propertyWithAnExceedinglyLongName3: string; 36 | propertyWithAnExceedinglyLongName4: string; 37 | propertyWithAnExceedinglyLongName5: string; 38 | propertyWithAnExceedinglyLongName6: string; 39 | propertyWithAnExceedinglyLongName7: string; 40 | propertyWithAnExceedinglyLongName8: string; 41 | }; 42 | 43 | // String representation of type of 'x' should be truncated in error message 44 | var s: string = x; 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/tsconfig/noUncheckedIndexedAccess.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Unchecked Indexed Access' 3 | oneline: 'Add `undefined` to a type when accessed using an index.' 4 | --- 5 | 6 | TypeScript has a way to describe objects which have unknown keys but known values on an object, via index signatures. 7 | 8 | ```ts twoslash 9 | interface EnvironmentVars { 10 | NAME: string; 11 | OS: string; 12 | 13 | // Unknown properties are covered by this index signature. 14 | [propName: string]: string; 15 | } 16 | 17 | declare const env: EnvironmentVars; 18 | 19 | // Declared as existing 20 | const sysName = env.NAME; 21 | const os = env.OS; 22 | // ^? 23 | 24 | // Not declared, but because of the index 25 | // signature, then it is considered a string 26 | const nodeEnv = env.NODE_ENV; 27 | // ^? 28 | ``` 29 | 30 | Turning on `noUncheckedIndexedAccess` will add `undefined` to any un-declared field in the type. 31 | 32 | ```ts twoslash 33 | interface EnvironmentVars { 34 | NAME: string; 35 | OS: string; 36 | 37 | // Unknown properties are covered by this index signature. 38 | [propName: string]: string; 39 | } 40 | // @noUncheckedIndexedAccess 41 | // ---cut--- 42 | declare const env: EnvironmentVars; 43 | 44 | // Declared as existing 45 | const sysName = env.NAME; 46 | const os = env.OS; 47 | // ^? 48 | 49 | // Not declared, but because of the index 50 | // signature, then it is considered a string 51 | const nodeEnv = env.NODE_ENV; 52 | // ^? 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/tsconfig/skipLibCheck.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Skip Lib Check' 3 | oneline: 'Skip type checking all .d.ts files.' 4 | --- 5 | 6 | Skip type checking of declaration files. 7 | 8 | This can save time during compilation at the expense of type-system accuracy. For example, two libraries could 9 | define two copies of the same `type` in an inconsistent way. Rather than doing a full check of all `d.ts` files, TypeScript 10 | will type check the code you specifically refer to in your app's source code. 11 | 12 | A common case where you might think to use `skipLibCheck` is when there are two copies of a library's types in 13 | your `node_modules`. In these cases, you should consider using a feature like [yarn's resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) 14 | to ensure there is only one copy of that dependency in your tree or investigate how to ensure there is 15 | only one copy by understanding the dependency resolution to fix the issue without additional tooling. 16 | 17 | Another possibility is when you are migrating between TypeScript releases and the changes cause breakages in node_modules and the JS standard libraries which you do not want to deal with during the TypeScript update. 18 | 19 | Note, that if these issues come from the TypeScript standard library you can replace the library using [TypeScript 4.5's lib replacement](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#supporting-lib-from-node_modules) technique. 20 | -------------------------------------------------------------------------------- /docs/tsconfig/paths.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Paths' 3 | oneline: 'Specify a set of entries that re-map imports to additional lookup locations.' 4 | --- 5 | 6 | A series of entries which re-map imports to lookup locations relative to the [`baseUrl`](#baseUrl) if set, or to the tsconfig file itself otherwise. There is a larger coverage of `paths` in [the `moduleResolution` reference page](/docs/handbook/modules/reference.html#paths). 7 | 8 | `paths` lets you declare how TypeScript should resolve an import in your `require`/`import`s. 9 | 10 | ```json tsconfig 11 | { 12 | "compilerOptions": { 13 | "paths": { 14 | "jquery": ["./vendor/jquery/dist/jquery"] 15 | } 16 | } 17 | } 18 | ``` 19 | 20 | This would allow you to be able to write `import "jquery"`, and get all of the correct typing locally. 21 | 22 | ```json tsconfig 23 | { 24 | "compilerOptions": { 25 | "paths": { 26 | "app/*": ["./src/app/*"], 27 | "config/*": ["./src/app/_config/*"], 28 | "environment/*": ["./src/environments/*"], 29 | "shared/*": ["./src/app/_shared/*"], 30 | "helpers/*": ["./src/helpers/*"], 31 | "tests/*": ["./src/tests/*"] 32 | } 33 | } 34 | } 35 | ``` 36 | 37 | In this case, you can tell the TypeScript file resolver to support a number of custom prefixes to find code. 38 | 39 | Note that this feature does not change how import paths are emitted by `tsc`, so `paths` should only be used to inform TypeScript that another tool has this mapping and will use it at runtime or when bundling. 40 | -------------------------------------------------------------------------------- /docs/tsconfig/customConditions.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Custom Conditions' 3 | oneline: 'Conditions to set in addition to the resolver-specific defaults when resolving imports.' 4 | --- 5 | 6 | `--customConditions` takes a list of additional [conditions](https://nodejs.org/api/packages.html#nested-conditions) that should succeed when TypeScript resolves from an [`exports`](https://nodejs.org/api/packages.html#exports) or [`imports`](https://nodejs.org/api/packages.html#imports) field of a `package.json`. 7 | These conditions are added to whatever existing conditions a resolver will use by default. 8 | 9 | For example, when this field is set in a `tsconfig.json` as so: 10 | 11 | ```jsonc 12 | { 13 | "compilerOptions": { 14 | "target": "es2022", 15 | "moduleResolution": "bundler", 16 | "customConditions": ["my-condition"], 17 | }, 18 | } 19 | ``` 20 | 21 | Any time an `exports` or `imports` field is referenced in `package.json`, TypeScript will consider conditions called `my-condition`. 22 | 23 | So when importing from a package with the following `package.json` 24 | 25 | ```jsonc 26 | { 27 | // ... 28 | "exports": { 29 | ".": { 30 | "my-condition": "./foo.mjs", 31 | "node": "./bar.mjs", 32 | "import": "./baz.mjs", 33 | "require": "./biz.mjs", 34 | }, 35 | }, 36 | } 37 | ``` 38 | 39 | TypeScript will try to look for files corresponding to `foo.mjs`. 40 | 41 | This field is only valid under the `node16`, `nodenext`, and `bundler` options for [`--moduleResolution`](#moduleResolution). 42 | -------------------------------------------------------------------------------- /docs/tsconfig/jsxFactory.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'JSX Factory' 3 | oneline: "Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'." 4 | --- 5 | 6 | Changes the function called in `.js` files when compiling JSX Elements using the classic JSX runtime. 7 | The most common change is to use `"h"` or `"preact.h"` instead of the default `"React.createElement"` if using `preact`. 8 | 9 | For example, this TSX file: 10 | 11 | ```tsx 12 | import { h } from 'preact'; 13 | 14 | const HelloWorld = () =>
Hello
; 15 | ``` 16 | 17 | With `jsxFactory: "h"` looks like: 18 | 19 | ```tsx twoslash 20 | // @showEmit 21 | // @showEmittedFile: index.js 22 | // @jsxFactory: h 23 | // @noErrors 24 | // @target: esnext 25 | // @module: commonjs 26 | 27 | import { h, Fragment } from 'preact'; 28 | 29 | const HelloWorld = () =>
Hello
; 30 | ``` 31 | 32 | This option can be used on a per-file basis too similar to [Babel's `/** @jsx h */` directive](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#custom). 33 | 34 | ```tsx twoslash 35 | /** @jsx h */ 36 | import { h } from 'preact'; 37 | 38 | const HelloWorld = () =>
Hello
; 39 | ``` 40 | 41 | The factory chosen will also affect where the `JSX` namespace is looked up (for type checking information) before falling back to the global one. 42 | 43 | If the factory is defined as `React.createElement` (the default), the compiler will check for `React.JSX` before checking for a global `JSX`. If the factory is defined as `h`, it will check for `h.JSX` before a global `JSX`. 44 | -------------------------------------------------------------------------------- /docs/tsconfig/strictFunctionTypes.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strict Function Types' 3 | oneline: 'When assigning functions, check to ensure parameters and the return values are subtype-compatible.' 4 | --- 5 | 6 | When enabled, this flag causes functions parameters to be checked more correctly. 7 | 8 | Here's a basic example with `strictFunctionTypes` off: 9 | 10 | ```ts twoslash 11 | // @strictFunctionTypes: false 12 | function fn(x: string) { 13 | console.log('Hello, ' + x.toLowerCase()); 14 | } 15 | 16 | type StringOrNumberFunc = (ns: string | number) => void; 17 | 18 | // Unsafe assignment 19 | let func: StringOrNumberFunc = fn; 20 | // Unsafe call - will crash 21 | func(10); 22 | ``` 23 | 24 | With `strictFunctionTypes` _on_, the error is correctly detected: 25 | 26 | ```ts twoslash 27 | // @errors: 2322 28 | function fn(x: string) { 29 | console.log('Hello, ' + x.toLowerCase()); 30 | } 31 | 32 | type StringOrNumberFunc = (ns: string | number) => void; 33 | 34 | // Unsafe assignment is prevented 35 | let func: StringOrNumberFunc = fn; 36 | ``` 37 | 38 | During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. 39 | Because of this, the setting only applies to functions written in _function_ syntax, not to those in _method_ syntax: 40 | 41 | ```ts twoslash 42 | type Methodish = { 43 | func(x: string | number): void; 44 | }; 45 | 46 | function fn(x: string) { 47 | console.log('Hello, ' + x.toLowerCase()); 48 | } 49 | 50 | // Ultimately an unsafe assignment, but not detected 51 | const m: Methodish = { 52 | func: fn, 53 | }; 54 | m.func(10); 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/tsconfig/jsxFragmentFactory.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'JSX Fragment Factory' 3 | oneline: "Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'." 4 | --- 5 | 6 | Specify the JSX fragment factory function to use when targeting react JSX emit with [`jsxFactory`](#jsxFactory) compiler option is specified, e.g. `Fragment`. 7 | 8 | For example with this TSConfig: 9 | 10 | ```json tsconfig 11 | { 12 | "compilerOptions": { 13 | "target": "esnext", 14 | "module": "commonjs", 15 | "jsx": "react", 16 | "jsxFactory": "h", 17 | "jsxFragmentFactory": "Fragment" 18 | } 19 | } 20 | ``` 21 | 22 | This TSX file: 23 | 24 | ```tsx 25 | import { h, Fragment } from 'preact'; 26 | 27 | const HelloWorld = () => ( 28 | <> 29 |
Hello
30 | 31 | ); 32 | ``` 33 | 34 | Would look like: 35 | 36 | ```tsx twoslash 37 | // @showEmit 38 | // @showEmittedFile: index.js 39 | // @jsxFactory: h 40 | // @jsxFragmentFactory: Fragment 41 | // @noErrors 42 | // @target: esnext 43 | // @module: commonjs 44 | 45 | import { h, Fragment } from 'preact'; 46 | 47 | const HelloWorld = () => ( 48 | <> 49 |
Hello
50 | 51 | ); 52 | ``` 53 | 54 | This option can be used on a per-file basis too similar to [Babel's `/* @jsxFrag h */` directive](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#fragments). 55 | 56 | For example: 57 | 58 | ```tsx twoslash 59 | /** @jsx h */ 60 | /** @jsxFrag Fragment */ 61 | 62 | import { h, Fragment } from 'preact'; 63 | 64 | const HelloWorld = () => ( 65 | <> 66 |
Hello
67 | 68 | ); 69 | ``` 70 | -------------------------------------------------------------------------------- /docs/tsconfig/extends.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Extends' 3 | oneline: 'Specify one or more path or node module references to base configuration files from which settings are inherited.' 4 | --- 5 | 6 | The value of `extends` is a string which contains a path to another configuration file to inherit from. 7 | The path may use Node.js style resolution. 8 | 9 | The configuration from the base file are loaded first, then overridden by those in the inheriting config file. All relative paths found in the configuration file will be resolved relative to the configuration file they originated in. 10 | 11 | It's worth noting that [`files`](#files), [`include`](#include), and [`exclude`](#exclude) from the inheriting config file _overwrite_ those from the 12 | base config file, and that circularity between configuration files is not allowed. 13 | 14 | Currently, the only top-level property that is excluded from inheritance is [`references`](#references). 15 | 16 | ##### Example 17 | 18 | `configs/base.json`: 19 | 20 | ```json tsconfig 21 | { 22 | "compilerOptions": { 23 | "noImplicitAny": true, 24 | "strictNullChecks": true 25 | } 26 | } 27 | ``` 28 | 29 | `tsconfig.json`: 30 | 31 | ```json tsconfig 32 | { 33 | "extends": "./configs/base", 34 | "files": ["main.ts", "supplemental.ts"] 35 | } 36 | ``` 37 | 38 | `tsconfig.nostrictnull.json`: 39 | 40 | ```json tsconfig 41 | { 42 | "extends": "./tsconfig", 43 | "compilerOptions": { 44 | "strictNullChecks": false 45 | } 46 | } 47 | ``` 48 | 49 | Properties with relative paths found in the configuration file, which aren't excluded from inheritance, will be resolved relative to the configuration file they originated in. 50 | -------------------------------------------------------------------------------- /docs/tsconfig/importHelpers.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Import Helpers' 3 | oneline: 'Allow importing helper functions from tslib once per project, instead of including them per-file.' 4 | --- 5 | 6 | For certain downleveling operations, TypeScript uses some helper code for operations like extending class, spreading arrays or objects, and async operations. 7 | By default, these helpers are inserted into files which use them. 8 | This can result in code duplication if the same helper is used in many different modules. 9 | 10 | If the `importHelpers` flag is on, these helper functions are instead imported from the [tslib](https://www.npmjs.com/package/tslib) module. 11 | You will need to ensure that the `tslib` module is able to be imported at runtime. 12 | This only affects modules; global script files will not attempt to import modules. 13 | 14 | For example, with this TypeScript: 15 | 16 | ```ts 17 | export function fn(arr: number[]) { 18 | const arr2 = [1, ...arr]; 19 | } 20 | ``` 21 | 22 | Turning on [`downlevelIteration`](#downlevelIteration) and `importHelpers` is still false: 23 | 24 | ```ts twoslash 25 | // @showEmit 26 | // @target: ES5 27 | // @downleveliteration 28 | export function fn(arr: number[]) { 29 | const arr2 = [1, ...arr]; 30 | } 31 | ``` 32 | 33 | Then turning on both [`downlevelIteration`](#downlevelIteration) and `importHelpers`: 34 | 35 | ```ts twoslash 36 | // @showEmit 37 | // @target: ES5 38 | // @downleveliteration 39 | // @importhelpers 40 | // @noErrors 41 | export function fn(arr: number[]) { 42 | const arr2 = [1, ...arr]; 43 | } 44 | ``` 45 | 46 | You can use [`noEmitHelpers`](#noEmitHelpers) when you provide your own implementations of these functions. 47 | -------------------------------------------------------------------------------- /docs/tsconfig/types.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Types' 3 | oneline: 'Specify type package names to be included without being referenced in a source file.' 4 | --- 5 | 6 | By default all _visible_ "`@types`" packages are included in your compilation. 7 | Packages in `node_modules/@types` of any enclosing folder are considered _visible_. 8 | For example, that means packages within `./node_modules/@types/`, `../node_modules/@types/`, `../../node_modules/@types/`, and so on. 9 | 10 | If `types` is specified, only packages listed will be included in the global scope. For instance: 11 | 12 | ```json tsconfig 13 | { 14 | "compilerOptions": { 15 | "types": ["node", "jest", "express"] 16 | } 17 | } 18 | ``` 19 | 20 | This `tsconfig.json` file will _only_ include `./node_modules/@types/node`, `./node_modules/@types/jest` and `./node_modules/@types/express`. 21 | Other packages under `node_modules/@types/*` will not be included. 22 | 23 | ### What does this affect? 24 | 25 | This option does not affect how `@types/*` are included in your application code, for example if you had the above `compilerOptions` example with code like: 26 | 27 | ```ts 28 | import * as moment from 'moment'; 29 | 30 | moment().format('MMMM Do YYYY, h:mm:ss a'); 31 | ``` 32 | 33 | The `moment` import would be fully typed. 34 | 35 | When you have this option set, by not including a module in the `types` array it: 36 | 37 | - Will not add globals to your project (e.g `process` in node, or `expect` in Jest) 38 | - Will not have exports appear as auto-import recommendations 39 | 40 | This feature differs from [`typeRoots`](#typeRoots) in that it is about specifying only the exact types you want included, whereas [`typeRoots`](#typeRoots) supports saying you want particular folders. 41 | -------------------------------------------------------------------------------- /docs/tsconfig/exactOptionalPropertyTypes.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Exact Optional Property Types' 3 | oneline: 'Interpret optional property types as written, rather than adding `undefined`.' 4 | --- 5 | 6 | With exactOptionalPropertyTypes enabled, TypeScript applies stricter rules around how it handles properties on `type` or `interfaces` which have a `?` prefix. 7 | 8 | For example, this interface declares that there is a property which can be one of two strings: 'dark' or 'light' or it should not be in the object. 9 | 10 | ```ts 11 | interface UserDefaults { 12 | // The absence of a value represents 'system' 13 | colorThemeOverride?: 'dark' | 'light'; 14 | } 15 | ``` 16 | 17 | Without this flag enabled, there are three values which you can set `colorThemeOverride` to be: "dark", "light" and `undefined`. 18 | 19 | Setting the value to `undefined` will allow most JavaScript runtime checks for the existence to fail, which is effectively falsy. However, this isn't quite accurate; `colorThemeOverride: undefined` is not the same as `colorThemeOverride` not being defined. For example, `"colorThemeOverride" in settings` would have different behavior with `undefined` as the key compared to not being defined. 20 | 21 | `exactOptionalPropertyTypes` makes TypeScript truly enforce the definition provided as an optional property: 22 | 23 | ```ts twoslash 24 | // @exactOptionalPropertyTypes 25 | // @errors: 2322 2412 26 | interface UserDefaults { 27 | colorThemeOverride?: 'dark' | 'light'; 28 | } 29 | declare function getUserSettings(): UserDefaults; 30 | // ---cut--- 31 | const settings = getUserSettings(); 32 | settings.colorThemeOverride = 'dark'; 33 | settings.colorThemeOverride = 'light'; 34 | 35 | // But not: 36 | settings.colorThemeOverride = undefined; 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/tsconfig/stripInternal.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strip Internal' 3 | oneline: 'Disable emitting declarations that have `@internal` in their JSDoc comments.' 4 | --- 5 | 6 | Do not emit declarations for code that has an `@internal` annotation in its JSDoc comment. 7 | This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. 8 | If you are searching for a tool to handle additional levels of visibility within your `d.ts` files, look at [api-extractor](https://api-extractor.com). 9 | 10 | ```ts twoslash 11 | /** 12 | * Days available in a week 13 | * @internal 14 | */ 15 | export const daysInAWeek = 7; 16 | 17 | /** Calculate how much someone earns in a week */ 18 | export function weeklySalary(dayRate: number) { 19 | return daysInAWeek * dayRate; 20 | } 21 | ``` 22 | 23 | With the flag set to `false` (default): 24 | 25 | ```ts twoslash 26 | // @showEmittedFile: index.d.ts 27 | // @showEmit 28 | // @declaration 29 | /** 30 | * Days available in a week 31 | * @internal 32 | */ 33 | export const daysInAWeek = 7; 34 | 35 | /** Calculate how much someone earns in a week */ 36 | export function weeklySalary(dayRate: number) { 37 | return daysInAWeek * dayRate; 38 | } 39 | ``` 40 | 41 | With `stripInternal` set to `true` the `d.ts` emitted will be redacted. 42 | 43 | ```ts twoslash 44 | // @stripinternal 45 | // @showEmittedFile: index.d.ts 46 | // @showEmit 47 | // @declaration 48 | /** 49 | * Days available in a week 50 | * @internal 51 | */ 52 | export const daysInAWeek = 7; 53 | 54 | /** Calculate how much someone earns in a week */ 55 | export function weeklySalary(dayRate: number) { 56 | return daysInAWeek * dayRate; 57 | } 58 | ``` 59 | 60 | The JavaScript output is still the same. 61 | -------------------------------------------------------------------------------- /docs/tsconfig/allowSyntheticDefaultImports.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Allow Synthetic Default Imports' 3 | oneline: "Allow 'import x from y' when a module doesn't have a default export." 4 | --- 5 | 6 | When set to true, `allowSyntheticDefaultImports` allows you to write an import like: 7 | 8 | ```ts 9 | import React from 'react'; 10 | ``` 11 | 12 | instead of: 13 | 14 | ```ts 15 | import * as React from 'react'; 16 | ``` 17 | 18 | When the module **does not** explicitly specify a default export. 19 | 20 | For example, without `allowSyntheticDefaultImports` as true: 21 | 22 | ```ts twoslash 23 | // @errors: 1259 1192 24 | // @checkJs 25 | // @allowJs 26 | // @esModuleInterop: false 27 | // @filename: utilFunctions.js 28 | // @noImplicitAny: false 29 | const getStringLength = (str) => str.length; 30 | 31 | module.exports = { 32 | getStringLength, 33 | }; 34 | 35 | // @filename: index.ts 36 | import utils from './utilFunctions'; 37 | 38 | const count = utils.getStringLength('Check JS'); 39 | ``` 40 | 41 | This code raises an error because there isn't a `default` object which you can import. Even though it feels like it should. 42 | For convenience, transpilers like Babel will automatically create a default if one isn't created. Making the module look a bit more like: 43 | 44 | ```js 45 | // @filename: utilFunctions.js 46 | const getStringLength = (str) => str.length; 47 | const allFunctions = { 48 | getStringLength, 49 | }; 50 | 51 | module.exports = allFunctions; 52 | module.exports.default = allFunctions; 53 | ``` 54 | 55 | This flag does not affect the JavaScript emitted by TypeScript, it's only for the type checking. 56 | This option brings the behavior of TypeScript in-line with Babel, where extra code is emitted to make using a default export of a module more ergonomic. 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ai-hero-cli", 3 | "version": "0.0.5", 4 | "bin": { 5 | "ai-hero": "./dist/bin.js" 6 | }, 7 | "description": "A CLI for AI Hero", 8 | "keywords": [ 9 | "ai", 10 | "hero", 11 | "cli" 12 | ], 13 | "homepage": "https://github.com/mattpocock/ai-hero-cli", 14 | "bugs": { 15 | "url": "https://github.com/mattpocock/ai-hero-cli/issues" 16 | }, 17 | "author": "Matt Pocock (https://aihero.dev)", 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/mattpocock/ai-hero-cli.git" 21 | }, 22 | "license": "MIT", 23 | "files": [ 24 | "dist", 25 | "docs", 26 | "prompts" 27 | ], 28 | "type": "module", 29 | "devDependencies": { 30 | "@arethetypeswrong/cli": "^0.18.2", 31 | "@changesets/cli": "^2.29.4", 32 | "@types/node": "^24.0.3", 33 | "prettier": "^3.5.3", 34 | "typescript": "^5.8.3", 35 | "vitest": "^3.2.4" 36 | }, 37 | "scripts": { 38 | "dev": "node --no-warnings --experimental-strip-types src/bin.ts", 39 | "ci": "npm run build && npm run check-format", 40 | "build": "tsc", 41 | "test": "vitest run", 42 | "format": "prettier --write .", 43 | "check-format": "prettier --check .", 44 | "local-release": "npm run ci && changeset version && changeset publish" 45 | }, 46 | "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee", 47 | "dependencies": { 48 | "@ai-sdk/anthropic": "^1.2.12", 49 | "@ai-sdk/google": "^1.2.19", 50 | "@ai-sdk/openai": "^1.3.22", 51 | "@clack/prompts": "^0.11.0", 52 | "@zod/mini": "4.0.0-beta.0", 53 | "ai": "^4.3.16", 54 | "commander": "^14.0.0", 55 | "jsonc-parser": "^3.3.1" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /docs/tsconfig/noPropertyAccessFromIndexSignature.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Property Access From Index Signature' 3 | oneline: 'Enforces using indexed accessors for keys declared using an indexed type.' 4 | --- 5 | 6 | This setting ensures consistency between accessing a field via the "dot" (`obj.key`) syntax, and "indexed" (`obj["key"]`) and the way which the property is declared in the type. 7 | 8 | Without this flag, TypeScript will allow you to use the dot syntax to access fields which are not defined: 9 | 10 | ```ts twoslash 11 | // @errors: 4111 12 | declare function getSettings(): GameSettings; 13 | // ---cut--- 14 | interface GameSettings { 15 | // Known up-front properties 16 | speed: 'fast' | 'medium' | 'slow'; 17 | quality: 'high' | 'low'; 18 | 19 | // Assume anything unknown to the interface 20 | // is a string. 21 | [key: string]: string; 22 | } 23 | 24 | const settings = getSettings(); 25 | settings.speed; 26 | // ^? 27 | settings.quality; 28 | // ^? 29 | 30 | // Unknown key accessors are allowed on 31 | // this object, and are `string` 32 | settings.username; 33 | // ^? 34 | ``` 35 | 36 | Turning the flag on will raise an error because the unknown field uses dot syntax instead of indexed syntax. 37 | 38 | ```ts twoslash 39 | // @errors: 4111 40 | // @noPropertyAccessFromIndexSignature 41 | declare function getSettings(): GameSettings; 42 | interface GameSettings { 43 | speed: 'fast' | 'medium' | 'slow'; 44 | quality: 'high' | 'low'; 45 | [key: string]: string; 46 | } 47 | // ---cut--- 48 | const settings = getSettings(); 49 | settings.speed; 50 | settings.quality; 51 | 52 | // This would need to be settings["username"]; 53 | settings.username; 54 | // ^? 55 | ``` 56 | 57 | The goal of this flag is to signal intent in your calling syntax about how certain you are this property exists. 58 | -------------------------------------------------------------------------------- /docs/tsconfig/explainFiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Explain Files' 3 | oneline: 'Print files read during the compilation including why it was included.' 4 | --- 5 | 6 | Print names of files which TypeScript sees as a part of your project and the reason they are part of the compilation. 7 | 8 | For example, with this project of just a single `index.ts` file 9 | 10 | ```sh 11 | example 12 | ├── index.ts 13 | ├── package.json 14 | └── tsconfig.json 15 | ``` 16 | 17 | Using a `tsconfig.json` which has `explainFiles` set to true: 18 | 19 | ```json 20 | { 21 | "compilerOptions": { 22 | "target": "es5", 23 | "module": "commonjs", 24 | "explainFiles": true 25 | } 26 | } 27 | ``` 28 | 29 | Running TypeScript against this folder would have output like this: 30 | 31 | ``` 32 | ❯ tsc 33 | node_modules/typescript/lib/lib.d.ts 34 | Default library for target 'es5' 35 | node_modules/typescript/lib/lib.es5.d.ts 36 | Library referenced via 'es5' from file 'node_modules/typescript/lib/lib.d.ts' 37 | node_modules/typescript/lib/lib.dom.d.ts 38 | Library referenced via 'dom' from file 'node_modules/typescript/lib/lib.d.ts' 39 | node_modules/typescript/lib/lib.webworker.importscripts.d.ts 40 | Library referenced via 'webworker.importscripts' from 41 | file 'node_modules/typescript/lib/lib.d.ts' 42 | node_modules/typescript/lib/lib.scripthost.d.ts 43 | Library referenced via 'scripthost' 44 | from file 'node_modules/typescript/lib/lib.d.ts' 45 | index.ts 46 | Matched by include pattern '**/*' in 'tsconfig.json' 47 | ``` 48 | 49 | The output above show: 50 | 51 | - The initial lib.d.ts lookup based on [`target`](#target), and the chain of `.d.ts` files which are referenced 52 | - The `index.ts` file located via the default pattern of [`include`](#include) 53 | 54 | This option is intended for debugging how a file has become a part of your compile. 55 | -------------------------------------------------------------------------------- /docs/tsconfig/noImplicitOverride.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'No Implicit Override' 3 | oneline: 'Ensure overriding members in derived classes are marked with an override modifier.' 4 | --- 5 | 6 | When working with classes which use inheritance, it's possible for a sub-class to get "out of sync" with the functions it overloads when they are renamed in the base class. 7 | 8 | For example, imagine you are modeling a music album syncing system: 9 | 10 | ```ts twoslash 11 | class Album { 12 | download() { 13 | // Default behavior 14 | } 15 | } 16 | 17 | class SharedAlbum extends Album { 18 | download() { 19 | // Override to get info from many sources 20 | } 21 | } 22 | ``` 23 | 24 | Then when you add support for machine-learning generated playlists, you refactor the `Album` class to have a 'setup' function instead: 25 | 26 | ```ts twoslash 27 | class Album { 28 | setup() { 29 | // Default behavior 30 | } 31 | } 32 | 33 | class MLAlbum extends Album { 34 | setup() { 35 | // Override to get info from algorithm 36 | } 37 | } 38 | 39 | class SharedAlbum extends Album { 40 | download() { 41 | // Override to get info from many sources 42 | } 43 | } 44 | ``` 45 | 46 | In this case, TypeScript has provided no warning that `download` on `SharedAlbum` _expected_ to override a function in the base class. 47 | 48 | Using `noImplicitOverride` you can ensure that the sub-classes never go out of sync, by ensuring that functions which override include the keyword `override`. 49 | 50 | The following example has `noImplicitOverride` enabled, and you can see the error received when `override` is missing: 51 | 52 | ```ts twoslash 53 | // @noImplicitOverride 54 | // @errors: 4114 55 | class Album { 56 | setup() {} 57 | } 58 | 59 | class MLAlbum extends Album { 60 | override setup() {} 61 | } 62 | 63 | class SharedAlbum extends Album { 64 | setup() {} 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/tsconfig/preserveConstEnums.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Preserve Const Enums' 3 | oneline: 'Disable erasing `const enum` declarations in generated code.' 4 | --- 5 | 6 | Do not erase `const enum` declarations in generated code. `const enum`s provide a way to reduce the overall memory footprint 7 | of your application at runtime by emitting the enum value instead of a reference. 8 | 9 | For example with this TypeScript: 10 | 11 | ```ts twoslash 12 | const enum Album { 13 | JimmyEatWorldFutures = 1, 14 | TubRingZooHypothesis = 2, 15 | DogFashionDiscoAdultery = 3, 16 | } 17 | 18 | const selectedAlbum = Album.JimmyEatWorldFutures; 19 | if (selectedAlbum === Album.JimmyEatWorldFutures) { 20 | console.log('That is a great choice.'); 21 | } 22 | ``` 23 | 24 | The default `const enum` behavior is to convert any `Album.Something` to the corresponding number literal, and to remove a reference 25 | to the enum from the JavaScript completely. 26 | 27 | ```ts twoslash 28 | // @showEmit 29 | const enum Album { 30 | JimmyEatWorldFutures = 1, 31 | TubRingZooHypothesis = 2, 32 | DogFashionDiscoAdultery = 3, 33 | } 34 | 35 | const selectedAlbum = Album.JimmyEatWorldFutures; 36 | if (selectedAlbum === Album.JimmyEatWorldFutures) { 37 | console.log('That is a great choice.'); 38 | } 39 | ``` 40 | 41 | With `preserveConstEnums` set to `true`, the `enum` exists at runtime and the numbers are still emitted. 42 | 43 | ```ts twoslash 44 | // @preserveConstEnums: true 45 | // @showEmit 46 | const enum Album { 47 | JimmyEatWorldFutures = 1, 48 | TubRingZooHypothesis = 2, 49 | DogFashionDiscoAdultery = 3, 50 | } 51 | 52 | const selectedAlbum = Album.JimmyEatWorldFutures; 53 | if (selectedAlbum === Album.JimmyEatWorldFutures) { 54 | console.log('That is a great choice.'); 55 | } 56 | ``` 57 | 58 | This essentially makes such `const enums` a source-code feature only, with no runtime traces. 59 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import { homedir } from 'os'; 2 | import path from 'path'; 3 | import { readFileSync, writeFileSync, existsSync } from 'fs'; 4 | import * as z from '@zod/mini'; 5 | import * as c from '@clack/prompts'; 6 | 7 | const configSchema = z.object({ 8 | provider: z.enum(['anthropic', 'openai', 'google']), 9 | apiKey: z.string(), 10 | }); 11 | 12 | const CONFIG_LOCATION = path.join(homedir(), '.ai-hero-config.json'); 13 | 14 | export type Config = z.output; 15 | 16 | export function readConfig(): Config | null { 17 | if (!existsSync(CONFIG_LOCATION)) { 18 | return null; 19 | } 20 | 21 | const configData = readFileSync(CONFIG_LOCATION, 'utf-8'); 22 | const parsed = configSchema.parse(JSON.parse(configData)); 23 | return parsed; 24 | } 25 | 26 | export function writeConfig(config: Config): void { 27 | const configData = JSON.stringify(config, null, 2); 28 | writeFileSync(CONFIG_LOCATION, configData, 'utf-8'); 29 | } 30 | 31 | export async function setupConfig(): Promise { 32 | const provider = await c.select({ 33 | message: 'Which AI provider do you want to use?', 34 | options: [ 35 | { label: 'Anthropic', value: 'anthropic' }, 36 | { label: 'OpenAI', value: 'openai' }, 37 | { label: 'Google', value: 'google' }, 38 | ], 39 | }); 40 | 41 | if (c.isCancel(provider)) { 42 | throw new Error('User cancelled'); 43 | } 44 | 45 | const apiKey = await c.password({ 46 | message: 'Enter your API key', 47 | mask: '*', 48 | }); 49 | 50 | if (c.isCancel(apiKey)) { 51 | throw new Error('User cancelled'); 52 | } 53 | 54 | writeConfig({ provider, apiKey }); 55 | 56 | return { provider, apiKey }; 57 | } 58 | 59 | export function setupConfigIfNeeded(): Promise { 60 | const config = readConfig(); 61 | if (config) { 62 | return Promise.resolve(config); 63 | } 64 | 65 | return setupConfig(); 66 | } 67 | -------------------------------------------------------------------------------- /docs/tsconfig/emitDecoratorMetadata.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Emit Decorator Metadata' 3 | oneline: 'Emit design-type metadata for decorated declarations in source files.' 4 | --- 5 | 6 | Enables experimental support for emitting type metadata for decorators which works with the module [`reflect-metadata`](https://www.npmjs.com/package/reflect-metadata). 7 | 8 | For example, here is the TypeScript 9 | 10 | ```ts twoslash 11 | // @experimentalDecorators 12 | function LogMethod( 13 | target: any, 14 | propertyKey: string | symbol, 15 | descriptor: PropertyDescriptor, 16 | ) { 17 | console.log(target); 18 | console.log(propertyKey); 19 | console.log(descriptor); 20 | } 21 | 22 | class Demo { 23 | @LogMethod 24 | public foo(bar: number) { 25 | // do nothing 26 | } 27 | } 28 | 29 | const demo = new Demo(); 30 | ``` 31 | 32 | With `emitDecoratorMetadata` not set to true (default) the emitted JavaScript is: 33 | 34 | ```ts twoslash 35 | // @experimentalDecorators 36 | // @showEmit 37 | function LogMethod( 38 | target: any, 39 | propertyKey: string | symbol, 40 | descriptor: PropertyDescriptor, 41 | ) { 42 | console.log(target); 43 | console.log(propertyKey); 44 | console.log(descriptor); 45 | } 46 | 47 | class Demo { 48 | @LogMethod 49 | public foo(bar: number) { 50 | // do nothing 51 | } 52 | } 53 | 54 | const demo = new Demo(); 55 | ``` 56 | 57 | With `emitDecoratorMetadata` set to true the emitted JavaScript is: 58 | 59 | ```ts twoslash 60 | // @experimentalDecorators 61 | // @showEmit 62 | // @emitDecoratorMetadata 63 | function LogMethod( 64 | target: any, 65 | propertyKey: string | symbol, 66 | descriptor: PropertyDescriptor, 67 | ) { 68 | console.log(target); 69 | console.log(propertyKey); 70 | console.log(descriptor); 71 | } 72 | 73 | class Demo { 74 | @LogMethod 75 | public foo(bar: number) { 76 | // do nothing 77 | } 78 | } 79 | 80 | const demo = new Demo(); 81 | ``` 82 | -------------------------------------------------------------------------------- /docs/tsconfig/allowArbitraryExtensions.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Allow Arbitrary Extensions' 3 | oneline: 'Enable importing files with any extension, provided a declaration file is present.' 4 | --- 5 | 6 | In TypeScript 5.0, when an import path ends in an extension that isn't a known JavaScript or TypeScript file extension, the compiler will look for a declaration file for that path in the form of `{file basename}.d.{extension}.ts`. 7 | For example, if you are using a CSS loader in a bundler project, you might want to write (or generate) declaration files for those stylesheets: 8 | 9 | ```css 10 | /* app.css */ 11 | .cookie-banner { 12 | display: none; 13 | } 14 | ``` 15 | 16 | ```ts 17 | // app.d.css.ts 18 | declare const css: { 19 | cookieBanner: string; 20 | }; 21 | export default css; 22 | ``` 23 | 24 | ```ts 25 | // App.tsx 26 | import styles from './app.css'; 27 | 28 | styles.cookieBanner; // string 29 | ``` 30 | 31 | By default, this import will raise an error to let you know that TypeScript doesn't understand this file type and your runtime might not support importing it. 32 | But if you've configured your runtime or bundler to handle it, you can suppress the error with the new `--allowArbitraryExtensions` compiler option. 33 | 34 | Note that historically, a similar effect has often been achievable by adding a declaration file named `app.css.d.ts` instead of `app.d.css.ts` - however, this just worked through Node's `require` resolution rules for CommonJS. 35 | Strictly speaking, the former is interpreted as a declaration file for a JavaScript file named `app.css.js`. 36 | Because relative files imports need to include extensions in Node's ESM support, TypeScript would error on our example in an ESM file under `--moduleResolution node16` or `nodenext`. 37 | 38 | For more information, read up [the proposal for this feature](https://github.com/microsoft/TypeScript/issues/50133) and [its corresponding pull request](https://github.com/microsoft/TypeScript/pull/51435). 39 | -------------------------------------------------------------------------------- /docs/tsconfig/strictNullChecks.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Strict Null Checks' 3 | oneline: 'When type checking, take into account `null` and `undefined`.' 4 | --- 5 | 6 | When `strictNullChecks` is `false`, `null` and `undefined` are effectively ignored by the language. 7 | This can lead to unexpected errors at runtime. 8 | 9 | When `strictNullChecks` is `true`, `null` and `undefined` have their own distinct types and you'll get a type error if you try to use them where a concrete value is expected. 10 | 11 | For example with this TypeScript code, `users.find` has no guarantee that it will actually find a user, but you can 12 | write code as though it will: 13 | 14 | ```ts twoslash 15 | // @strictNullChecks: false 16 | // @target: ES2015 17 | declare const loggedInUsername: string; 18 | 19 | const users = [ 20 | { name: 'Oby', age: 12 }, 21 | { name: 'Heera', age: 32 }, 22 | ]; 23 | 24 | const loggedInUser = users.find((u) => u.name === loggedInUsername); 25 | console.log(loggedInUser.age); 26 | ``` 27 | 28 | Setting `strictNullChecks` to `true` will raise an error that you have not made a guarantee that the `loggedInUser` exists before trying to use it. 29 | 30 | ```ts twoslash 31 | // @errors: 2339 2532 18048 32 | // @target: ES2020 33 | // @strictNullChecks 34 | declare const loggedInUsername: string; 35 | 36 | const users = [ 37 | { name: 'Oby', age: 12 }, 38 | { name: 'Heera', age: 32 }, 39 | ]; 40 | 41 | const loggedInUser = users.find((u) => u.name === loggedInUsername); 42 | console.log(loggedInUser.age); 43 | ``` 44 | 45 | The second example failed because the array's `find` function looks a bit like this simplification: 46 | 47 | ```ts 48 | // When strictNullChecks: true 49 | type Array = { 50 | find(predicate: (value: any, index: number) => boolean): S | undefined; 51 | }; 52 | 53 | // When strictNullChecks: false the undefined is removed from the type system, 54 | // allowing you to write code which assumes it always found a result 55 | type Array = { 56 | find(predicate: (value: any, index: number) => boolean): S; 57 | }; 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/tsconfig/include.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Include' 3 | oneline: 'Specify a list of glob patterns that match files to be included in compilation.' 4 | --- 5 | 6 | Specifies an array of filenames or patterns to include in the program. 7 | These filenames are resolved relative to the directory containing the `tsconfig.json` file. 8 | 9 | ```json 10 | { 11 | "include": ["src/**/*", "tests/**/*"] 12 | } 13 | ``` 14 | 15 | Which would include: 16 | 17 | 38 | 39 | ``` 40 | . 41 | ├── scripts ⨯ 42 | │ ├── lint.ts ⨯ 43 | │ ├── update_deps.ts ⨯ 44 | │ └── utils.ts ⨯ 45 | ├── src ✓ 46 | │ ├── client ✓ 47 | │ │ ├── index.ts ✓ 48 | │ │ └── utils.ts ✓ 49 | │ ├── server ✓ 50 | │ │ └── index.ts ✓ 51 | ├── tests ✓ 52 | │ ├── app.test.ts ✓ 53 | │ ├── utils.ts ✓ 54 | │ └── tests.d.ts ✓ 55 | ├── package.json 56 | ├── tsconfig.json 57 | └── yarn.lock 58 | ``` 59 | 60 | `include` and `exclude` support wildcard characters to make glob patterns: 61 | 62 | - `*` matches zero or more characters (excluding directory separators) 63 | - `?` matches any one character (excluding directory separators) 64 | - `**/` matches any directory nested to any level 65 | 66 | If the last path segment in a pattern does not contain a file extension or wildcard character, then it is treated as a directory, and files with supported extensions inside that directory are included (e.g. `.ts`, `.tsx`, and `.d.ts` by default, with `.js` and `.jsx` if [`allowJs`](#allowJs) is set to true). 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AI Hero CLI 2 | 3 | A fun set of experiments with AI and TypeScript. 4 | 5 | ## Usage 6 | 7 | No installation required! Run directly with npx: 8 | 9 | ```bash 10 | npx ai-hero-cli@latest 11 | ``` 12 | 13 | ## Quick Start 14 | 15 | ### 1. Setup 16 | 17 | First, configure your AI provider: 18 | 19 | ```bash 20 | npx ai-hero-cli@latest setup 21 | ``` 22 | 23 | This will guide you through setting up your preferred AI model (OpenAI, Anthropic, or Google). 24 | 25 | ### 2. Analyze Your tsconfig.json 26 | 27 | ```bash 28 | npx ai-hero-cli@latest hows-my-tsconfig 29 | ``` 30 | 31 | This will analyze your `tsconfig.json` file and provide: 32 | 33 | - Detailed recommendations for improvement 34 | - A score for your current configuration 35 | - Interactive Q&A session for follow-up questions 36 | 37 | You can also specify a custom path: 38 | 39 | ```bash 40 | npx ai-hero-cli@latest hows-my-tsconfig ./path/to/your/tsconfig.json 41 | ``` 42 | 43 | ## What It Does 44 | 45 | The AI Hero CLI analyzes your TypeScript configuration and provides expert recommendations based on: 46 | 47 | - **Best Practices**: Suggests modern TypeScript patterns and settings 48 | - **Performance**: Recommends optimizations for build times and runtime 49 | - **Type Safety**: Identifies opportunities to catch more bugs at compile time 50 | - **Developer Experience**: Suggests settings that improve IDE support and debugging 51 | 52 | ### Key Recommendations Include 53 | 54 | - Enabling `strict: true` for maximum type safety 55 | - Setting appropriate `target` and `lib` values 56 | - Configuring module resolution for your project type 57 | - Removing redundant or deprecated options 58 | - Adding useful flags like `noUnusedLocals` and `noUnusedParameters` 59 | 60 | ## Commands 61 | 62 | ### `ai-hero setup` 63 | 64 | Configure your AI provider and API keys. 65 | 66 | ### `ai-hero hows-my-tsconfig [path]` 67 | 68 | Analyze your TypeScript configuration file. Defaults to `tsconfig.json` in the current directory. 69 | 70 | ## Supported AI Providers 71 | 72 | - **OpenAI** (GPT-4, GPT-3.5-turbo) 73 | - **Anthropic** (Claude) 74 | - **Google** (Gemini) 75 | -------------------------------------------------------------------------------- /docs/tsconfig/rootDirs.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Root Dirs' 3 | oneline: 'Allow multiple folders to be treated as one when resolving modules.' 4 | --- 5 | 6 | Using `rootDirs`, you can inform the compiler that there are many "virtual" directories acting as a single root. 7 | This allows the compiler to resolve relative module imports within these "virtual" directories, as if they were merged in to one directory. 8 | 9 | For example: 10 | 11 | ``` 12 | src 13 | └── views 14 | └── view1.ts (can import "./template1", "./view2`) 15 | └── view2.ts (can import "./template1", "./view1`) 16 | 17 | generated 18 | └── templates 19 | └── views 20 | └── template1.ts (can import "./view1", "./view2") 21 | ``` 22 | 23 | ```json tsconfig 24 | { 25 | "compilerOptions": { 26 | "rootDirs": ["src/views", "generated/templates/views"] 27 | } 28 | } 29 | ``` 30 | 31 | This does not affect how TypeScript emits JavaScript, it only emulates the assumption that they will be able to 32 | work via those relative paths at runtime. 33 | 34 | `rootDirs` can be used to provide a separate "type layer" to files that are not TypeScript or JavaScript by providing a home for generated `.d.ts` files in another folder. This technique is useful for bundled applications where you use `import` of files that aren't necessarily code: 35 | 36 | ```sh 37 | src 38 | └── index.ts 39 | └── css 40 | └── main.css 41 | └── navigation.css 42 | 43 | generated 44 | └── css 45 | └── main.css.d.ts 46 | └── navigation.css.d.ts 47 | ``` 48 | 49 | ```json tsconfig 50 | { 51 | "compilerOptions": { 52 | "rootDirs": ["src", "generated"] 53 | } 54 | } 55 | ``` 56 | 57 | This technique lets you generate types ahead of time for the non-code source files. Imports then work naturally based off the source file's location. 58 | For example `./src/index.ts` can import the file `./src/css/main.css` and TypeScript will be aware of the bundler's behavior for that filetype via the corresponding generated declaration file. 59 | 60 | ```ts twoslash 61 | // @filename: main.css.d.ts 62 | export const appClass = 'mainClassF3EC2'; 63 | // ---cut--- 64 | // @filename: index.ts 65 | import { appClass } from './main.css'; 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/tsconfig/rootDir.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Root Dir' 3 | oneline: 'Specify the root folder within your source files.' 4 | --- 5 | 6 | **Default**: The longest common path of all non-declaration input files. If [`composite`](#composite) is set, the default is instead the directory containing the `tsconfig.json` file. 7 | 8 | When TypeScript compiles files, it keeps the same directory structure in the output directory as exists in the input directory. 9 | 10 | For example, let's say you have some input files: 11 | 12 | ``` 13 | MyProj 14 | ├── tsconfig.json 15 | ├── core 16 | │ ├── a.ts 17 | │ ├── b.ts 18 | │ ├── sub 19 | │ │ ├── c.ts 20 | ├── types.d.ts 21 | ``` 22 | 23 | The inferred value for `rootDir` is the longest common path of all non-declaration input files, which in this case is `core/`. 24 | 25 | If your [`outDir`](#outDir) was `dist`, TypeScript would write this tree: 26 | 27 | ``` 28 | MyProj 29 | ├── dist 30 | │ ├── a.js 31 | │ ├── b.js 32 | │ ├── sub 33 | │ │ ├── c.js 34 | ``` 35 | 36 | However, you may have intended for `core` to be part of the output directory structure. 37 | By setting `rootDir: "."` in `tsconfig.json`, TypeScript would write this tree: 38 | 39 | ``` 40 | MyProj 41 | ├── dist 42 | │ ├── core 43 | │ │ ├── a.js 44 | │ │ ├── b.js 45 | │ │ ├── sub 46 | │ │ │ ├── c.js 47 | ``` 48 | 49 | Importantly, `rootDir` **does not affect which files become part of the compilation**. 50 | It has no interaction with the [`include`](#include), [`exclude`](#exclude), or [`files`](#files) `tsconfig.json` settings. 51 | 52 | Note that TypeScript will never write an output file to a directory outside of [`outDir`](#outDir), and will never skip emitting a file. 53 | For this reason, `rootDir` also enforces that all files which need to be emitted are underneath the `rootDir` path. 54 | 55 | For example, let's say you had this tree: 56 | 57 | ``` 58 | MyProj 59 | ├── tsconfig.json 60 | ├── core 61 | │ ├── a.ts 62 | │ ├── b.ts 63 | ├── helpers.ts 64 | ``` 65 | 66 | It would be an error to specify `rootDir` as `core` _and_ [`include`](#include) as `*` because it creates a file (`helpers.ts`) that would need to be emitted _outside_ the [`outDir`](#outDir) (i.e. `../helpers.js`). 67 | -------------------------------------------------------------------------------- /docs/tsconfig/noUncheckedSideEffectImports.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'noUncheckedSideEffectImports' 3 | oneline: 'Check side effect imports.' 4 | --- 5 | 6 | In JavaScript it's possible to `import` a module without actually importing any values from it. 7 | 8 | ```ts 9 | import 'some-module'; 10 | ``` 11 | 12 | These imports are often called _side effect imports_ because the only useful behavior they can provide is by executing some side effect (like registering a global variable, or adding a polyfill to a prototype). 13 | 14 | By default, TypeScript will not check these imports for validity. If the import resolves to a valid source file, TypeScript will load and check the file. 15 | If no source file is found, TypeScript will silently ignore the import. 16 | 17 | This is surprising behavior, but it partially stems from modeling patterns in the JavaScript ecosystem. 18 | For example, this syntax has also been used with special loaders in bundlers to load CSS or other assets. 19 | Your bundler might be configured in such a way where you can include specific `.css` files by writing something like the following: 20 | 21 | ```tsx 22 | import './button-component.css'; 23 | 24 | export function Button() { 25 | // ... 26 | } 27 | ``` 28 | 29 | Still, this masks potential typos on side effect imports. 30 | 31 | When `--noUncheckedSideEffectImports` is enabled, TypeScript will error if it can't find a source file for a side effect import. 32 | 33 | ```ts 34 | import 'oops-this-module-does-not-exist'; 35 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | // error: Cannot find module 'oops-this-module-does-not-exist' or its corresponding 37 | // type declarations. 38 | ``` 39 | 40 | When enabling this option, some working code may now receive an error, like in the CSS example above. 41 | To work around this, users who want to just write side effect `import`s for assets might be better served by writing what's called an _ambient module declaration_ with a wildcard specifier. 42 | It would go in a global file and look something like the following: 43 | 44 | ```ts 45 | // ./src/globals.d.ts 46 | 47 | // Recognize all CSS files as module imports. 48 | declare module '*.css' {} 49 | ``` 50 | 51 | In fact, you might already have a file like this in your project! 52 | For example, running something like `vite init` might create a similar `vite-env.d.ts`. 53 | -------------------------------------------------------------------------------- /docs/tsconfig/erasableSyntaxOnly.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Erasable Syntax Only' 3 | oneline: 'Do not allow runtime constructs that are not part of ECMAScript.' 4 | --- 5 | 6 | Node.js [supports running TypeScript files directly](https://nodejs.org/api/typescript.html#type-stripping) as of v23.6; 7 | however, only TypeScript-specific syntax that does not have runtime semantics are supported under this mode. 8 | In other words, it must be possible to easily _erase_ any TypeScript-specific syntax from a file, leaving behind a valid JavaScript file. 9 | 10 | That means the following constructs are not supported: 11 | 12 | - `enum` declarations 13 | - `namespace`s and `module`s with runtime code 14 | - parameter properties in classes 15 | - Non-ECMAScript `import =` and `export =` assignments 16 | 17 | ```ts 18 | // ❌ error: An `import ... = require(...)` alias 19 | import foo = require('foo'); 20 | 21 | // ❌ error: A namespace with runtime code. 22 | namespace container { 23 | foo.method(); 24 | 25 | export type Bar = string; 26 | } 27 | 28 | // ❌ error: An `import =` alias 29 | import Bar = container.Bar; 30 | 31 | class Point { 32 | // ❌ error: Parameter properties 33 | constructor( 34 | public x: number, 35 | public y: number, 36 | ) {} 37 | } 38 | 39 | // ❌ error: An `export =` assignment. 40 | export = Point; 41 | 42 | // ❌ error: An enum declaration. 43 | enum Direction { 44 | Up, 45 | Down, 46 | Left, 47 | Right, 48 | } 49 | ``` 50 | 51 | Similar tools like [ts-blank-space](https://github.com/bloomberg/ts-blank-space) or [Amaro](https://github.com/nodejs/amaro) (the underlying library for type-stripping in Node.js) have the same limitations. 52 | These tools will provide helpful error messages if they encounter code that doesn't meet these requirements, but you still won't find out your code doesn't work until you actually try to run it. 53 | 54 | The `--erasableSyntaxOnly` flag will cause TypeScript to error on most TypeScript-specific constructs that have runtime behavior. 55 | 56 | ```ts 57 | class C { 58 | constructor(public x: number) { } 59 | // ~~~~~~~~~~~~~~~~ 60 | // error! This syntax is not allowed when 'erasableSyntaxOnly' is enabled. 61 | } 62 | } 63 | ``` 64 | 65 | Typically, you will want to combine this flag with the `--verbatimModuleSyntax`, which ensures that a module contains the appropriate import syntax, and that import elision does not take place. 66 | -------------------------------------------------------------------------------- /docs/tsconfig/jsxImportSource.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'JSX Import Source' 3 | oneline: 'Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.' 4 | --- 5 | 6 | Declares the module specifier to be used for importing the `jsx` and `jsxs` factory functions when using [`jsx`](#jsx) as `"react-jsx"` or `"react-jsxdev"` which were introduced in TypeScript 4.1. 7 | 8 | With [React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) the library supports a new form of JSX transformation via a separate import. 9 | 10 | For example with this code: 11 | 12 | ```tsx 13 | import React from 'react'; 14 | 15 | function App() { 16 | return

Hello World

; 17 | } 18 | ``` 19 | 20 | Using this TSConfig: 21 | 22 | ```json tsconfig 23 | { 24 | "compilerOptions": { 25 | "target": "esnext", 26 | "module": "commonjs", 27 | "jsx": "react-jsx" 28 | } 29 | } 30 | ``` 31 | 32 | The emitted JavaScript from TypeScript is: 33 | 34 | ```tsx twoslash 35 | // @showEmit 36 | // @noErrors 37 | // @jsx: react-jsx 38 | // @module: commonjs 39 | // @target: esnext 40 | declare module JSX { 41 | interface Element {} 42 | interface IntrinsicElements { 43 | [s: string]: any; 44 | } 45 | } 46 | import React from 'react'; 47 | 48 | function App() { 49 | return

Hello World

; 50 | } 51 | ``` 52 | 53 | For example if you wanted to use `"jsxImportSource": "preact"`, you need a tsconfig like: 54 | 55 | ```json tsconfig 56 | { 57 | "compilerOptions": { 58 | "target": "esnext", 59 | "module": "commonjs", 60 | "jsx": "react-jsx", 61 | "jsxImportSource": "preact", 62 | "types": ["preact"] 63 | } 64 | } 65 | ``` 66 | 67 | Which generates code like: 68 | 69 | ```tsx twoslash 70 | // @showEmit 71 | // @jsxImportSource: preact 72 | // @types: preact 73 | // @jsx: react-jsx 74 | // @target: esnext 75 | // @module: commonjs 76 | // @noErrors 77 | 78 | export function App() { 79 | return

Hello World

; 80 | } 81 | ``` 82 | 83 | Alternatively, you can use a per-file pragma to set this option, for example: 84 | 85 | ```tsx 86 | /** @jsxImportSource preact */ 87 | 88 | export function App() { 89 | return

Hello World

; 90 | } 91 | ``` 92 | 93 | Would add `preact/jsx-runtime` as an import for the `_jsx` factory. 94 | 95 | _Note:_ In order for this to work like you would expect, your `tsx` file must include an `export` or `import` so that it is considered a module. 96 | -------------------------------------------------------------------------------- /docs/tsconfig/isolatedModules.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Isolated Modules' 3 | oneline: 'Ensure that each file can be safely transpiled without relying on other imports.' 4 | --- 5 | 6 | While you can use TypeScript to produce JavaScript code from TypeScript code, it's also common to use other transpilers such as [Babel](https://babeljs.io) to do this. 7 | However, other transpilers only operate on a single file at a time, which means they can't apply code transforms that depend on understanding the full type system. 8 | This restriction also applies to TypeScript's `ts.transpileModule` API which is used by some build tools. 9 | 10 | These limitations can cause runtime problems with some TypeScript features like `const enum`s and `namespace`s. 11 | Setting the `isolatedModules` flag tells TypeScript to warn you if you write certain code that can't be correctly interpreted by a single-file transpilation process. 12 | 13 | It does not change the behavior of your code, or otherwise change the behavior of TypeScript's checking and emitting process. 14 | 15 | Some examples of code which does not work when `isolatedModules` is enabled. 16 | 17 | #### Exports of Non-Value Identifiers 18 | 19 | In TypeScript, you can import a _type_ and then subsequently export it: 20 | 21 | ```ts twoslash 22 | // @noErrors 23 | import { someType, someFunction } from 'someModule'; 24 | 25 | someFunction(); 26 | 27 | export { someType, someFunction }; 28 | ``` 29 | 30 | Because there's no value for `someType`, the emitted `export` will not try to export it (this would be a runtime error in JavaScript): 31 | 32 | ```js 33 | export { someFunction }; 34 | ``` 35 | 36 | Single-file transpilers don't know whether `someType` produces a value or not, so it's an error to export a name that only refers to a type. 37 | 38 | #### Non-Module Files 39 | 40 | If `isolatedModules` is set, namespaces are only allowed in _modules_ (which means it has some form of `import`/`export`). An error occurs if a namespace is found in a non-module file: 41 | 42 | ```ts twoslash 43 | // @errors: 1277 44 | // @isolatedModules 45 | namespace Instantiated { 46 | export const x = 1; 47 | } 48 | ``` 49 | 50 | This restriction doesn't apply to `.d.ts` files. 51 | 52 | #### References to `const enum` members 53 | 54 | In TypeScript, when you reference a `const enum` member, the reference is replaced by its actual value in the emitted JavaScript. Changing this TypeScript: 55 | 56 | ```ts twoslash 57 | declare const enum Numbers { 58 | Zero = 0, 59 | One = 1, 60 | } 61 | console.log(Numbers.Zero + Numbers.One); 62 | ``` 63 | 64 | To this JavaScript: 65 | 66 | ```ts twoslash 67 | // @showEmit 68 | // @removeComments 69 | declare const enum Numbers { 70 | Zero = 0, 71 | One = 1, 72 | } 73 | console.log(Numbers.Zero + Numbers.One); 74 | ``` 75 | 76 | Without knowledge of the values of these members, other transpilers can't replace the references to `Numbers`, which would be a runtime error if left alone (since there are no `Numbers` object at runtime). 77 | Because of this, when `isolatedModules` is set, it is an error to reference an ambient `const enum` member. 78 | -------------------------------------------------------------------------------- /docs/tsconfig/jsx.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'JSX' 3 | oneline: 'Specify what JSX code is generated.' 4 | --- 5 | 6 | Controls how JSX constructs are emitted in JavaScript files. 7 | This only affects output of JS files that started in `.tsx` files. 8 | 9 | - `react-jsx`: Emit `.js` files with the JSX changed to `_jsx` calls optimized for production 10 | - `react-jsxdev`: Emit `.js` files with the JSX changed to `_jsx` calls for development only 11 | - `preserve`: Emit `.jsx` files with the JSX unchanged 12 | - `react-native`: Emit `.js` files with the JSX unchanged 13 | - `react`: Emit `.js` files with JSX changed to the equivalent `React.createElement` calls 14 | 15 | ### For example 16 | 17 | This sample code: 18 | 19 | ```tsx 20 | export const HelloWorld = () =>

Hello world

; 21 | ``` 22 | 23 | React: `"react-jsx"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) 24 | 25 | ```tsx twoslash 26 | declare module JSX { 27 | interface Element {} 28 | interface IntrinsicElements { 29 | [s: string]: any; 30 | } 31 | } 32 | // @showEmit 33 | // @noErrors 34 | // @jsx: react-jsx 35 | export const HelloWorld = () =>

Hello world

; 36 | ``` 37 | 38 | React dev transform: `"react-jsxdev"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) 39 | 40 | ```tsx twoslash 41 | declare module JSX { 42 | interface Element {} 43 | interface IntrinsicElements { 44 | [s: string]: any; 45 | } 46 | } 47 | // @showEmit 48 | // @noErrors 49 | // @jsx: react-jsxdev 50 | export const HelloWorld = () =>

Hello world

; 51 | ``` 52 | 53 | Preserve: `"preserve"` 54 | 55 | ```tsx twoslash 56 | declare module JSX { 57 | interface Element {} 58 | interface IntrinsicElements { 59 | [s: string]: any; 60 | } 61 | } 62 | // @showEmit 63 | // @noErrors 64 | // @jsx: preserve 65 | export const HelloWorld = () =>

Hello world

; 66 | ``` 67 | 68 | React Native: `"react-native"` 69 | 70 | ```tsx twoslash 71 | declare module JSX { 72 | interface Element {} 73 | interface IntrinsicElements { 74 | [s: string]: any; 75 | } 76 | } 77 | // @showEmit 78 | // @noErrors 79 | // @jsx: react-native 80 | export const HelloWorld = () =>

Hello world

; 81 | ``` 82 | 83 | Legacy React runtime: `"react"` 84 | 85 | ```tsx twoslash 86 | declare module JSX { 87 | interface Element {} 88 | interface IntrinsicElements { 89 | [s: string]: any; 90 | } 91 | } 92 | // @showEmit 93 | // @noErrors 94 | export const HelloWorld = () =>

Hello world

; 95 | ``` 96 | 97 | This option can be used on a per-file basis too using an `@jsxRuntime` comment. 98 | 99 | Always use the classic runtime (`"react"`) for this file: 100 | 101 | ```tsx 102 | /* @jsxRuntime classic */ 103 | export const HelloWorld = () =>

Hello world

; 104 | ``` 105 | 106 | Always use the automatic runtime (`"react-jsx"`) for this file: 107 | 108 | ```tsx 109 | /* @jsxRuntime automatic */ 110 | export const HelloWorld = () =>

Hello world

; 111 | ``` 112 | -------------------------------------------------------------------------------- /docs/tsconfig/esModuleInterop.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'ES Module Interop' 3 | oneline: 'Emit additional JavaScript to ease support for importing CommonJS modules. This enables [`allowSyntheticDefaultImports`](#allowSyntheticDefaultImports) for type compatibility.' 4 | --- 5 | 6 | By default (with `esModuleInterop` false or not set) TypeScript treats CommonJS/AMD/UMD modules similar to ES6 modules. In doing this, there are two parts in particular which turned out to be flawed assumptions: 7 | 8 | - a namespace import like `import * as moment from "moment"` acts the same as `const moment = require("moment")` 9 | 10 | - a default import like `import moment from "moment"` acts the same as `const moment = require("moment").default` 11 | 12 | This mis-match causes these two issues: 13 | 14 | - the ES6 modules spec states that a namespace import (`import * as x`) can only be an object, by having TypeScript 15 | treating it the same as `= require("x")` then TypeScript allowed for the import to be treated as a function and be callable. That's not valid according to the spec. 16 | 17 | - while accurate to the ES6 modules spec, most libraries with CommonJS/AMD/UMD modules didn't conform as strictly as TypeScript's implementation. 18 | 19 | Turning on `esModuleInterop` will fix both of these problems in the code transpiled by TypeScript. The first changes the behavior in the compiler, the second is fixed by two new helper functions which provide a shim to ensure compatibility in the emitted JavaScript: 20 | 21 | ```ts 22 | import * as fs from 'fs'; 23 | import _ from 'lodash'; 24 | 25 | fs.readFileSync('file.txt', 'utf8'); 26 | _.chunk(['a', 'b', 'c', 'd'], 2); 27 | ``` 28 | 29 | With `esModuleInterop` disabled: 30 | 31 | ```ts twoslash 32 | // @noErrors 33 | // @showEmit 34 | // @esModuleInterop: false 35 | // @module: commonjs 36 | import * as fs from 'fs'; 37 | import _ from 'lodash'; 38 | 39 | fs.readFileSync('file.txt', 'utf8'); 40 | _.chunk(['a', 'b', 'c', 'd'], 2); 41 | ``` 42 | 43 | With `esModuleInterop` set to `true`: 44 | 45 | ```ts twoslash 46 | // @noErrors 47 | // @showEmit 48 | // @esModuleInterop 49 | // @module: commonjs 50 | import * as fs from 'fs'; 51 | import _ from 'lodash'; 52 | 53 | fs.readFileSync('file.txt', 'utf8'); 54 | _.chunk(['a', 'b', 'c', 'd'], 2); 55 | ``` 56 | 57 | _Note_: The namespace import `import * as fs from "fs"` only accounts for properties which [are owned](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) (basically properties set on the object and not via the prototype chain) on the imported object. If the module you're importing defines its API using inherited properties, you need to use the default import form (`import fs from "fs"`), or disable `esModuleInterop`. 58 | 59 | _Note_: You can make JS emit terser by enabling [`importHelpers`](#importHelpers): 60 | 61 | ```ts twoslash 62 | // @noErrors 63 | // @showEmit 64 | // @esModuleInterop 65 | // @importHelpers 66 | // @module: commonjs 67 | import * as fs from 'fs'; 68 | import _ from 'lodash'; 69 | 70 | fs.readFileSync('file.txt', 'utf8'); 71 | _.chunk(['a', 'b', 'c', 'd'], 2); 72 | ``` 73 | 74 | Enabling `esModuleInterop` will also enable [`allowSyntheticDefaultImports`](#allowSyntheticDefaultImports). 75 | -------------------------------------------------------------------------------- /docs/tsconfig/downlevelIteration.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Downlevel Iteration' 3 | oneline: 'Emit more compliant, but verbose and less performant JavaScript for iteration.' 4 | --- 5 | 6 | Downleveling is TypeScript's term for transpiling to an older version of JavaScript. 7 | This flag is to enable support for a more accurate implementation of how modern JavaScript iterates through new concepts in older JavaScript runtimes. 8 | 9 | ECMAScript 6 added several new iteration primitives: the `for / of` loop (`for (el of arr)`), Array spread (`[a, ...b]`), argument spread (`fn(...args)`), and `Symbol.iterator`. 10 | `downlevelIteration` allows for these iteration primitives to be used more accurately in ES5 environments if a `Symbol.iterator` implementation is present. 11 | 12 | #### Example: Effects on `for / of` 13 | 14 | With this TypeScript code: 15 | 16 | ```ts twoslash 17 | const str = 'Hello!'; 18 | for (const s of str) { 19 | console.log(s); 20 | } 21 | ``` 22 | 23 | Without `downlevelIteration` enabled, a `for / of` loop on any object is downleveled to a traditional `for` loop: 24 | 25 | ```ts twoslash 26 | // @target: ES5 27 | // @showEmit 28 | const str = 'Hello!'; 29 | for (const s of str) { 30 | console.log(s); 31 | } 32 | ``` 33 | 34 | This is often what people expect, but it's not 100% compliant with ECMAScript iteration protocol. 35 | Certain strings, such as emoji (😜), have a `.length` of 2 (or even more!), but should iterate as 1 unit in a `for-of` loop. 36 | See [this blog post by Jonathan New](https://blog.jonnew.com/posts/poo-dot-length-equals-two) for a longer explanation. 37 | 38 | When `downlevelIteration` is enabled, TypeScript will use a helper function that checks for a `Symbol.iterator` implementation (either native or polyfill). 39 | If this implementation is missing, you'll fall back to index-based iteration. 40 | 41 | ```ts twoslash 42 | // @target: ES5 43 | // @downlevelIteration 44 | // @showEmit 45 | const str = 'Hello!'; 46 | for (const s of str) { 47 | console.log(s); 48 | } 49 | ``` 50 | 51 | You can use [tslib](https://www.npmjs.com/package/tslib) via [`importHelpers`](#importHelpers) to reduce the amount of inline JavaScript too: 52 | 53 | ```ts twoslash 54 | // @target: ES5 55 | // @downlevelIteration 56 | // @importHelpers 57 | // @showEmit 58 | const str = 'Hello!'; 59 | for (const s of str) { 60 | console.log(s); 61 | } 62 | ``` 63 | 64 | **Note:** enabling `downlevelIteration` does not improve compliance if `Symbol.iterator` is not present in the runtime. 65 | 66 | #### Example: Effects on Array Spreads 67 | 68 | This is an array spread: 69 | 70 | ```js 71 | // Make a new array whose elements are 1 followed by the elements of arr2 72 | const arr = [1, ...arr2]; 73 | ``` 74 | 75 | Based on the description, it sounds easy to downlevel to ES5: 76 | 77 | ```js 78 | // The same, right? 79 | const arr = [1].concat(arr2); 80 | ``` 81 | 82 | However, this is observably different in certain rare cases. 83 | 84 | For example, if a source array is missing one or more items (contains a hole), the spread syntax will replace each empty item with `undefined`, whereas `.concat` will leave them intact. 85 | 86 | ```js 87 | // Make an array where the element at index 1 is missing 88 | let arrayWithHole = ['a', , 'c']; 89 | let spread = [...arrayWithHole]; 90 | let concatenated = [].concat(arrayWithHole); 91 | 92 | console.log(arrayWithHole); 93 | // [ 'a', <1 empty item>, 'c' ] 94 | console.log(spread); 95 | // [ 'a', undefined, 'c' ] 96 | console.log(concatenated); 97 | // [ 'a', <1 empty item>, 'c' ] 98 | ``` 99 | 100 | Just as with `for / of`, `downlevelIteration` will use `Symbol.iterator` (if present) to more accurately emulate ES 6 behavior. 101 | -------------------------------------------------------------------------------- /src/command.ts: -------------------------------------------------------------------------------- 1 | import * as c from '@clack/prompts'; 2 | import { generateText, smoothStream, streamText, type CoreMessage } from 'ai'; 3 | import { Command } from 'commander'; 4 | import { readFileSync } from 'fs'; 5 | import { readFile } from 'fs/promises'; 6 | import { parse } from 'jsonc-parser'; 7 | import path from 'path'; 8 | import type { CompilerOptions } from 'typescript'; 9 | import { setupConfig, setupConfigIfNeeded } from './config.ts'; 10 | import { getModel } from './model.ts'; 11 | 12 | export const command = new Command(); 13 | 14 | const getDocsForTSConfigOption = (option: keyof CompilerOptions) => { 15 | try { 16 | return readFileSync( 17 | path.resolve(import.meta.dirname, `../docs/tsconfig/${option}.md`), 18 | 'utf8', 19 | ); 20 | } catch (error) { 21 | c.log.warn(`No docs found for ${option}`); 22 | return ''; 23 | } 24 | }; 25 | 26 | command 27 | .command('hows-my-tsconfig [tsconfig-path]') 28 | .action(async (tsconfigPath = 'tsconfig.json') => { 29 | c.intro("OK, let's check your tsconfig.json for you."); 30 | 31 | const config = await setupConfigIfNeeded(); 32 | 33 | const models = getModel(config); 34 | 35 | const tsconfig = await readFile(tsconfigPath, 'utf8'); 36 | 37 | const parsedTsconfig = parse(tsconfig); 38 | 39 | const compilerOptions = parsedTsconfig.compilerOptions as CompilerOptions; 40 | 41 | if (!compilerOptions) { 42 | c.log.error('No compilerOptions found in tsconfig.json'); 43 | c.outro(); 44 | return; 45 | } 46 | 47 | const docs = Object.keys(compilerOptions).map((option) => { 48 | return { 49 | option, 50 | docs: getDocsForTSConfigOption(option as keyof CompilerOptions), 51 | }; 52 | }); 53 | 54 | const system = readFileSync( 55 | path.resolve(import.meta.dirname, '../prompts/hows-my-tsconfig.md'), 56 | 'utf8', 57 | ).replace( 58 | '{{docs}}', 59 | docs.map((doc) => `### ${doc.option}\n\n${doc.docs}`).join('\n\n'), 60 | ); 61 | 62 | const messages: CoreMessage[] = [ 63 | { 64 | role: 'system', 65 | content: system, 66 | }, 67 | { 68 | role: 'user', 69 | content: tsconfig, 70 | }, 71 | ]; 72 | 73 | const thoughts = streamText({ 74 | model: models.thoughts, 75 | messages, 76 | onError: ({ error }) => { 77 | if (error instanceof Error) { 78 | c.log.error(error.message); 79 | } else { 80 | c.log.error('An unknown error occurred'); 81 | } 82 | }, 83 | experimental_transform: [ 84 | smoothStream({ 85 | chunking: 'word', 86 | }), 87 | ], 88 | }); 89 | 90 | await c.stream.message(thoughts.textStream); 91 | 92 | messages.push({ 93 | role: 'assistant', 94 | content: await thoughts.text, 95 | }); 96 | 97 | const score = await generateText({ 98 | model: models.score, 99 | system: readFileSync( 100 | path.resolve( 101 | import.meta.dirname, 102 | '../prompts/hows-my-tsconfig-score.md', 103 | ), 104 | 'utf8', 105 | ), 106 | prompt: await thoughts.text, 107 | }); 108 | 109 | c.log.success(await score.text); 110 | 111 | messages.push({ 112 | role: 'assistant', 113 | content: score.text, 114 | }); 115 | 116 | while (true) { 117 | const response = await c.text({ 118 | message: 'Ask a question', 119 | placeholder: '', 120 | }); 121 | 122 | if (c.isCancel(response)) { 123 | break; 124 | } 125 | 126 | messages.push({ 127 | role: 'user', 128 | content: response, 129 | }); 130 | 131 | const followup = streamText({ 132 | model: models.thoughts, 133 | messages, 134 | }); 135 | 136 | await c.stream.message(followup.textStream); 137 | 138 | messages.push({ 139 | role: 'assistant', 140 | content: await followup.text, 141 | }); 142 | } 143 | 144 | c.outro('Goodbye!'); 145 | }); 146 | 147 | command 148 | .command('setup') 149 | .description('Setup the AI Hero CLI with the AI you want to use') 150 | .action(async () => { 151 | await setupConfig(); 152 | c.outro('Setup complete'); 153 | }); 154 | -------------------------------------------------------------------------------- /prompts/hows-my-tsconfig.md: -------------------------------------------------------------------------------- 1 | Your name is Matt Pocock. You are a senior software engineer. You are a TypeScript expert. 2 | 3 | You are given a tsconfig.json file. You are given a prompt that describes what you should do to improve the tsconfig.json file. 4 | 5 | You are to respond with a list of changes you would make to the tsconfig.json file. 6 | 7 | You should recommend to the user that they read the TSConfig Cheat Sheet: https://www.totaltypescript.com/tsconfig-cheat-sheet 8 | 9 | ## Rules 10 | 11 | If the tsconfig has `forceConsistentCasingInFileNames`, recommend removing it. It's set to `true` by default since TypeScript 5.0. 12 | 13 | If the tsconfig has `erasableSyntaxOnly`, pat the user on the back and say they're fighting the good fight against enums, namespaces and class parameter properties. 14 | 15 | If the tsconfig does not have `noImplicitOverride`, recommend adding it. 16 | 17 | Do not recommend `exactOptionalPropertyTypes` - but don't say to remove it either. It's fine if you like it, but I personally don't. 18 | 19 | If the user does not have `lib` set, recommend adding it. They can set it to the same value as `target`. `lib` can be used to exclude the `dom` types if needed. Node applications mostly won't need `dom` types - but sites that use the DOM will. 20 | 21 | If they have `dom` in `lib`, then ensure they also have `dom.iterable` there too. 22 | 23 | `noUncheckedIndexedAccess: true` is a useful option to have because it catches errors where you might be accessing an index that doesn't exist. But if the user doesn't want it, don't push them to add it. 24 | 25 | `moduleDetection: "force"` forces every non-declaration file to be treated as a module. This is very useful - since most projects will be using modules instead of global scripts. 26 | 27 | If the tsconfig doesn't have `strict: true`, strongly recommend adding it. This is the most important setting for catching bugs early. 28 | 29 | If the user has `strict: true` but also has individual strict flags set explicitly, recommend removing the redundant ones since `strict: true` includes them all. 30 | 31 | For projects that need to be extra safe, recommend `noUnusedLocals: true` and `noUnusedParameters: true` to catch dead code. 32 | 33 | ### Module Options 34 | 35 | There are only two valid options for `module`: `Preserve` and `NodeNext`. 36 | 37 | If the user has `noEmit` set to `false`, or not specified, then the best config for them is `module: "NodeNext"`. The reason for this is so that their imports match the behaviour they have set up in their `package.json`. If they have `package.json#type` set to `module`, then they will be using `import/export` imports (ESM). If they have `package.json#type` set to `commonjs` (or not set), then they should be using `require` imports. 38 | 39 | If the user has `moduleResolution` set to `node`, recommend they use `NodeNext` instead and remove the `moduleResolution` option. 40 | 41 | If the user is targeting modern environments (ES2020+), recommend setting `target` to `"ES2022"` or higher for better performance. 42 | 43 | For projects using modern JavaScript features, recommend `allowUnreachableCode: false` to catch dead code. 44 | 45 | If the user is building a library, recommend `declaration: true` to generate `.d.ts` files. 46 | 47 | For better IDE experience, recommend `sourceMap: true` to enable debugging of TypeScript files. 48 | 49 | If the user is using a bundler like Vite or Webpack, they might want `noEmit: true` since the bundler handles compilation. 50 | 51 | ## Implicit Inheritances 52 | 53 | If some tsconfig.json options are set to `true`, others are automatically set to `true` as well. This means that the user doesn't need to set them. 54 | 55 | `verbatimModuleSyntax: true` -> `isolatedModules: true` 56 | 57 | `strict: true` -> `noImplicitAny: true`, `noImplicitThis: true`, `strictNullChecks: true`, `strictFunctionTypes: true`, `strictBindCallApply: true`, `strictPropertyInitialization: true`, `noImplicitReturns: true`, `useUnknownInCatchVariables: true`, `strictBuiltinIteratorReturn: true` 58 | 59 | `esModuleInterop: true` -> `allowSyntheticDefaultImports: true` 60 | 61 | `module: "node16"` -> `moduleResolution: "node16"` 62 | 63 | `module: "node18"` -> `moduleResolution: "node18"` 64 | 65 | `module: "nodenext"` -> `moduleResolution: "nodenext"` 66 | 67 | `target: "ES2022"` -> `lib: ["ES2022", "DOM", "DOM.Iterable"]` (if lib is not explicitly set) 68 | 69 | ## Docs 70 | 71 | Below, I've added the docs for each of the options that are set in the tsconfig.json file. 72 | 73 | Use the docs to help you understand the options and how they work. Also use them to inform your recommendations. 74 | 75 | {{docs}} 76 | -------------------------------------------------------------------------------- /docs/tsconfig/module.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Module' 3 | oneline: 'Specify what module code is generated.' 4 | --- 5 | 6 | Sets the module system for the program. See the [theory behind TypeScript’s `module` option](/docs/handbook/modules/theory.html#the-module-output-format) and [its reference page](/docs/handbook/modules/reference.html#the-module-compiler-option) for more information. You very likely want `"nodenext"` for modern Node.js projects and `preserve` or `esnext` for code that will be bundled. 7 | 8 | Changing `module` affects [`moduleResolution`](#moduleResolution) which [also has a reference page](/docs/handbook/modules/reference.html#the-moduleresolution-compiler-option). 9 | 10 | Here's some example output for this file: 11 | 12 | ```ts twoslash 13 | // @filename: constants.ts 14 | export const valueOfPi = 3.142; 15 | // ---cut--- 16 | // @filename: index.ts 17 | import { valueOfPi } from './constants'; 18 | 19 | export const twoPi = valueOfPi * 2; 20 | ``` 21 | 22 | #### `CommonJS` 23 | 24 | ```ts twoslash 25 | // @showEmit 26 | // @module: commonjs 27 | // @noErrors 28 | import { valueOfPi } from './constants'; 29 | 30 | export const twoPi = valueOfPi * 2; 31 | ``` 32 | 33 | #### `UMD` 34 | 35 | ```ts twoslash 36 | // @showEmit 37 | // @module: umd 38 | // @noErrors 39 | import { valueOfPi } from './constants'; 40 | 41 | export const twoPi = valueOfPi * 2; 42 | ``` 43 | 44 | #### `AMD` 45 | 46 | ```ts twoslash 47 | // @showEmit 48 | // @module: amd 49 | // @noErrors 50 | import { valueOfPi } from './constants'; 51 | 52 | export const twoPi = valueOfPi * 2; 53 | ``` 54 | 55 | #### `System` 56 | 57 | ```ts twoslash 58 | // @showEmit 59 | // @module: system 60 | // @noErrors 61 | import { valueOfPi } from './constants'; 62 | 63 | export const twoPi = valueOfPi * 2; 64 | ``` 65 | 66 | #### `ESNext` 67 | 68 | ```ts twoslash 69 | // @showEmit 70 | // @module: esnext 71 | // @noErrors 72 | import { valueOfPi } from './constants'; 73 | 74 | export const twoPi = valueOfPi * 2; 75 | ``` 76 | 77 | #### `ES2015`/`ES6`/`ES2020`/`ES2022` 78 | 79 | ```ts twoslash 80 | // @showEmit 81 | // @module: es2015 82 | // @noErrors 83 | import { valueOfPi } from './constants'; 84 | 85 | export const twoPi = valueOfPi * 2; 86 | ``` 87 | 88 | In addition to the base functionality of `ES2015`/`ES6`, `ES2020` adds support for [dynamic `import`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import), and [`import.meta`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta) while `ES2022` further adds support for [top level `await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await). 89 | 90 | #### `node16`/`node18`/`nodenext` 91 | 92 | The `node16`, `node18`, and `nodenext` modes integrate with Node's [native ECMAScript Module support](https://nodejs.org/api/esm.html). The emitted JavaScript uses either `CommonJS` or `ES2020` output depending on the file extension and the value of the `type` setting in the nearest `package.json`. Module resolution also works differently. You can learn more in the [handbook](/docs/handbook/esm-node.html) and [Modules Reference](/docs/handbook/modules/reference.html#node16-node18-nodenext). 93 | 94 | - `node16` is available from TypeScript 4.7 95 | - `node18` is available from TypeScript 5.8 as a replacement for `node16`, with added support for import attributes. 96 | - `nodenext` is available from TypeScript 4.7, but its behavior changes with the latest stable versions of Node.js. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules. 97 | 98 | #### `preserve` 99 | 100 | In `--module preserve` ([added](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html#support-for-require-calls-in---moduleresolution-bundler-and---module-preserve) in TypeScript 5.4), ECMAScript imports and exports written in input files are preserved in the output, and CommonJS-style `import x = require("...")` and `export = ...` statements are emitted as CommonJS `require` and `module.exports`. In other words, the format of each individual import or export statement is preserved, rather than being coerced into a single format for the whole compilation (or even a whole file). 101 | 102 | ```ts twoslash 103 | // @showEmit 104 | // @module: preserve 105 | // @noErrors 106 | import { valueOfPi } from './constants'; 107 | import constants = require('./constants'); 108 | 109 | export const piSquared = valueOfPi * constants.valueOfPi; 110 | ``` 111 | 112 | While it’s rare to need to mix imports and require calls in the same file, this `module` mode best reflects the capabilities of most modern bundlers, as well as the Bun runtime. 113 | 114 | > Why care about TypeScript’s `module` emit with a bundler or with Bun, where you’re likely also setting `noEmit`? TypeScript’s type checking and module resolution behavior are affected by the module format that it _would_ emit. Setting `module` gives TypeScript information about how your bundler or runtime will process imports and exports, which ensures that the types you see on imported values accurately reflect what will happen at runtime or after bundling. 115 | 116 | #### `None` 117 | 118 | ```ts twoslash 119 | // @showEmit 120 | // @module: none 121 | // @noErrors 122 | import { valueOfPi } from './constants'; 123 | 124 | export const twoPi = valueOfPi * 2; 125 | ``` 126 | -------------------------------------------------------------------------------- /docs/tsconfig/lib.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Lib' 3 | oneline: 'Specify a set of bundled library declaration files that describe the target runtime environment.' 4 | --- 5 | 6 | TypeScript includes a default set of type definitions for built-in JS APIs (like `Math`), as well as type definitions for things found in browser environments (like `document`). 7 | TypeScript also includes APIs for newer JS features matching the [`target`](#target) you specify; for example the definition for `Map` is available if [`target`](#target) is `ES6` or newer. 8 | 9 | You may want to change these for a few reasons: 10 | 11 | - Your program doesn't run in a browser, so you don't want the `"dom"` type definitions 12 | - Your runtime platform provides certain JavaScript API objects (maybe through polyfills), but doesn't yet support the full syntax of a given ECMAScript version 13 | - You have polyfills or native implementations for some, but not all, of a higher level ECMAScript version 14 | 15 | In TypeScript 4.5, lib files can be overridden by npm modules, find out more [in the blog](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#supporting-lib-from-node_modules). 16 | 17 | ### High Level libraries 18 | 19 | | Name | Contents | 20 | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | 21 | | `ES5` | Core definitions for all ES5 functionality | 22 | | `ES2015` | Additional APIs available in ES2015 (also known as ES6) - `array.find`, `Promise`, `Proxy`, `Symbol`, `Map`, `Set`, `Reflect`, etc. | 23 | | `ES6` | Alias for "ES2015" | 24 | | `ES2016` | Additional APIs available in ES2016 - `array.include`, etc. | 25 | | `ES7` | Alias for "ES2016" | 26 | | `ES2017` | Additional APIs available in ES2017 - `Object.entries`, `Object.values`, `Atomics`, `SharedArrayBuffer`, `date.formatToParts`, typed arrays, etc. | 27 | | `ES2018` | Additional APIs available in ES2018 - `async` iterables, `promise.finally`, `Intl.PluralRules`, `regexp.groups`, etc. | 28 | | `ES2019` | Additional APIs available in ES2019 - `array.flat`, `array.flatMap`, `Object.fromEntries`, `string.trimStart`, `string.trimEnd`, etc. | 29 | | `ES2020` | Additional APIs available in ES2020 - `string.matchAll`, etc. | 30 | | `ES2021` | Additional APIs available in ES2021 - `promise.any`, `string.replaceAll` etc. | 31 | | `ES2022` | Additional APIs available in ES2022 - `array.at`, `RegExp.hasIndices`, etc. | 32 | | `ES2023` | Additional APIs available in ES2023 - `array.with`, `array.findLast`, `array.findLastIndex`, `array.toSorted`, `array.toReversed`, etc. | 33 | | `ESNext` | Additional APIs available in ESNext - This changes as the JavaScript specification evolves | 34 | | `DOM` | [DOM](https://developer.mozilla.org/docs/Glossary/DOM) definitions - `window`, `document`, etc. | 35 | | `WebWorker` | APIs available in [WebWorker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers) contexts | 36 | | `ScriptHost` | APIs for the [Windows Script Hosting System](https://wikipedia.org/wiki/Windows_Script_Host) | 37 | 38 | ### Individual library components 39 | 40 | | Name | 41 | | ------------------------- | 42 | | `DOM.Iterable` | 43 | | `ES2015.Core` | 44 | | `ES2015.Collection` | 45 | | `ES2015.Generator` | 46 | | `ES2015.Iterable` | 47 | | `ES2015.Promise` | 48 | | `ES2015.Proxy` | 49 | | `ES2015.Reflect` | 50 | | `ES2015.Symbol` | 51 | | `ES2015.Symbol.WellKnown` | 52 | | `ES2016.Array.Include` | 53 | | `ES2017.object` | 54 | | `ES2017.Intl` | 55 | | `ES2017.SharedMemory` | 56 | | `ES2017.String` | 57 | | `ES2017.TypedArrays` | 58 | | `ES2018.Intl` | 59 | | `ES2018.Promise` | 60 | | `ES2018.RegExp` | 61 | | `ES2019.Array` | 62 | | `ES2019.Object` | 63 | | `ES2019.String` | 64 | | `ES2019.Symbol` | 65 | | `ES2020.String` | 66 | | `ES2020.Symbol.wellknown` | 67 | | `ES2021.Promise` | 68 | | `ES2021.String` | 69 | | `ES2021.WeakRef` | 70 | | `ESNext.AsyncIterable` | 71 | | `ESNext.Array` | 72 | | `ESNext.Intl` | 73 | | `ESNext.Symbol` | 74 | 75 | This list may be out of date, you can see the full list in the [TypeScript source code](https://github.com/microsoft/TypeScript/tree/main/src/lib). 76 | -------------------------------------------------------------------------------- /docs/tsconfig/verbatimModuleSyntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | display: 'Verbatim Module Syntax' 3 | oneline: "Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting." 4 | --- 5 | 6 | By default, TypeScript does something called _import elision_. 7 | Basically, if you write something like 8 | 9 | ```ts 10 | import { Car } from './car'; 11 | 12 | export function drive(car: Car) { 13 | // ... 14 | } 15 | ``` 16 | 17 | TypeScript detects that you're only using an import for types and drops the import entirely. 18 | Your output JavaScript might look something like this: 19 | 20 | ```js 21 | export function drive(car) { 22 | // ... 23 | } 24 | ``` 25 | 26 | Most of the time this is good, because if `Car` isn't a value that's exported from `./car`, we'll get a runtime error. 27 | 28 | But it does add a layer of complexity for certain edge cases. 29 | For example, notice there's no statement like `import "./car";` - the import was dropped entirely. 30 | That actually makes a difference for modules that have side-effects or not. 31 | 32 | TypeScript's emit strategy for JavaScript also has another few layers of complexity - import elision isn't always just driven by how an import is used - it often consults how a value is declared as well. 33 | So it's not always clear whether code like the following 34 | 35 | ```ts 36 | export { Car } from './car'; 37 | ``` 38 | 39 | should be preserved or dropped. 40 | If `Car` is declared with something like a `class`, then it can be preserved in the resulting JavaScript file. 41 | But if `Car` is only declared as a `type` alias or `interface`, then the JavaScript file shouldn't export `Car` at all. 42 | 43 | While TypeScript might be able to make these emit decisions based on information from across files, not every compiler can. 44 | 45 | The `type` modifier on imports and exports helps with these situations a bit. 46 | We can make it explicit whether an import or export is only being used for type analysis, and can be dropped entirely in JavaScript files by using the `type` modifier. 47 | 48 | ```ts 49 | // This statement can be dropped entirely in JS output 50 | import type * as car from './car'; 51 | 52 | // The named import/export 'Car' can be dropped in JS output 53 | import { type Car } from './car'; 54 | export { type Car } from './car'; 55 | ``` 56 | 57 | `type` modifiers are not quite useful on their own - by default, module elision will still drop imports, and nothing forces you to make the distinction between `type` and plain imports and exports. 58 | So TypeScript has the flag `--importsNotUsedAsValues` to make sure you use the `type` modifier, `--preserveValueImports` to prevent _some_ module elision behavior, and `--isolatedModules` to make sure that your TypeScript code works across different compilers. 59 | Unfortunately, understanding the fine details of those 3 flags is hard, and there are still some edge cases with unexpected behavior. 60 | 61 | TypeScript 5.0 introduces a new option called `--verbatimModuleSyntax` to simplify the situation. 62 | The rules are much simpler - any imports or exports without a `type` modifier are left around. 63 | Anything that uses the `type` modifier is dropped entirely. 64 | 65 | ```ts 66 | // Erased away entirely. 67 | import type { A } from 'a'; 68 | 69 | // Rewritten to 'import { b } from "bcd";' 70 | import { b, type c, type d } from 'bcd'; 71 | 72 | // Rewritten to 'import {} from "xyz";' 73 | import { type xyz } from 'xyz'; 74 | ``` 75 | 76 | With this new option, what you see is what you get. 77 | 78 | That does have some implications when it comes to module interop though. 79 | Under this flag, ECMAScript `import`s and `export`s won't be rewritten to `require` calls when your settings or file extension implied a different module system. 80 | Instead, you'll get an error. 81 | If you need to emit code that uses `require` and `module.exports`, you'll have to use TypeScript's module syntax that predates ES2015: 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 99 | 106 | 107 | 108 | 123 | 138 | 139 |
Input TypeScriptOutput JavaScript
93 | 94 | ```ts 95 | import foo = require('foo'); 96 | ``` 97 | 98 | 100 | 101 | ```js 102 | const foo = require('foo'); 103 | ``` 104 | 105 |
109 | 110 | ```ts 111 | function foo() {} 112 | function bar() {} 113 | function baz() {} 114 | 115 | export = { 116 | foo, 117 | bar, 118 | baz, 119 | }; 120 | ``` 121 | 122 | 124 | 125 | ```js 126 | function foo() {} 127 | function bar() {} 128 | function baz() {} 129 | 130 | module.exports = { 131 | foo, 132 | bar, 133 | baz, 134 | }; 135 | ``` 136 | 137 |
140 | 141 | While this is a limitation, it does help make some issues more obvious. 142 | For example, it's very common to forget to set the [`type` field in `package.json`](https://nodejs.org/api/packages.html#type) under `--module node16`. 143 | As a result, developers would start writing CommonJS modules instead of ES modules without realizing it, giving surprising lookup rules and JavaScript output. 144 | This new flag ensures that you're intentional about the file type you're using because the syntax is intentionally different. 145 | 146 | Because `--verbatimModuleSyntax` provides a more consistent story than `--importsNotUsedAsValues` and `--preserveValueImports`, those two existing flags are being deprecated in its favor. 147 | 148 | For more details, read up on [the original pull request](https://github.com/microsoft/TypeScript/pull/52203) and [its proposal issue](https://github.com/microsoft/TypeScript/issues/51479). 149 | --------------------------------------------------------------------------------