What does k6 do with a .ts test file, and what does it deliberately not do?
answer
- no build step, no tsconfig
- stripping, not compiling
- esbuild only as a fallback
- the .ts extension gates it
- types are never checked at run time
basics
~20 sk6 runs a .ts file directly by stripping its type annotations with esbuild, then executing the plain JavaScript. It never type-checks and never reads a tsconfig.json, so a wrong annotation costs nothing at run time.
solid answer
~40 sIn k6 v2 you just run `k6 run script.ts`; no build step, no bundler, no `tsconfig.json`. Internally k6 first tries to parse the file with **Sobek**, its JavaScript engine. Only if that parse fails, and only if the filename ends in `.ts` or the source came from standard input, does k6 hand the source to **esbuild** with the TypeScript loader, take the stripped output and a source map, and parse that. The transform is a deletion, not a compilation: annotations disappear, modern syntax is not down-levelled, and **nothing is type-checked**. So a wrong type never fails a k6 run — only a real syntax error does. Rename the same file to `.js` and it stops working, because the fallback is keyed on the extension.
code
bash · 2 linesk6 run script.ts # runs directly; no tsc, no bundler, no flag
k6 run - < script.ts # stdin also gets the type-stripping fallbackgo deeper
Remember that k6 run script.ts just works, and that the .ts extension is what makes it work. Do not expect k6 to tell you a type is wrong.
Explain the order of operations: Sobek parses first, esbuild strips types only as a fallback keyed on the .ts extension or stdin, and the stripped output is re-parsed with a source map so stack traces stay useful.
Show where the safety actually comes from. Since k6 verifies nothing, put a type-checking step in the pipeline that runs the test sources, and do not let a green k6 run stand in for it.
Decide the team's position on typed test code: whether the checking step is mandatory, where the k6 type definitions are pinned, and whether shared helpers ship as .ts sources or as pre-bundled JavaScript.
## Running TypeScript with no build step `k6 run script.ts` works out of the box in k6 v2. There is no `tsc` invocation, no bundler step, no plugin to install — and, importantly, **no `tsconfig.json` is read**: k6's binary contains no reference to one. What k6 does is much narrower than "supporting TypeScript", and the interview value of the question is in the gap between those two descriptions. ## The parse-then-strip pipeline k6 does not transpile every file. The sequence for each source file it loads is: 1. Hand the source to **Sobek**, k6's JavaScript engine, and parse it as-is. 2. If it parses, stop. The file runs; no transform tool is involved at all. A `.ts` file that happens to contain no annotations takes this path. 3. If the parse fails, check the file's identity: does the name end in `.ts`, or did the source arrive on standard input? 4. If neither is true, return the parse error unchanged — the run stops. 5. If one is true, hand the original source to **esbuild** with its TypeScript loader, take the stripped output plus a source map, and parse that instead. So esbuild is a *fallback keyed on the filename*, not an unconditional pre-processing stage. ## What esbuild is configured to do | configured behaviour | consequence for your script | |---|---| | TypeScript loader | annotations, `interface`, `type` and similar are removed | | target set to the newest ECMAScript level | **no** down-levelling of modern syntax | | external source map produced | stack traces still point at your `.ts` lines | | neutral platform | no Node or browser shims are injected | | no type checker in the pipeline | **types are never verified** | The transform is a deletion, not a compilation. `let t: string = "something";` becomes exactly `let t = "something";`. Nothing is added, nothing is polyfilled, nothing is checked. The k6 documentation states this plainly: TypeScript support is partial, because it strips the type information but does not provide type safety. ## The file extension is load-bearing Because step 3 keys on the name, the extension is not cosmetic: - Rename `script.ts` to `script.js` without changing a character of its contents and it stops working. Sobek fails to parse the annotations, the file is neither `.ts` nor standard input, and the parse error is returned. - The same rule applies to imported files, one file at a time: `./helpers.ts` gets the fallback, a `./helpers.js` that contains annotations does not. - k6 resolves module specifiers the way a browser does, with no extension guessing, so you import `./helpers.ts` under exactly that name — `./helpers` resolves to nothing. - Standard input is the one exception to the name rule: piping a script in with `k6 run -` gets the same fallback even though there is no filename to inspect. ## Type errors are not test failures There is no type checker anywhere in the path, so a wrong annotation is invisible at run time. A field typed `string` that actually holds a number, a function called with the wrong argument type, an interface that no longer matches the payload you parse — all of these run happily and fail, if at all, as ordinary JavaScript errors much later. What *does* stop the run is a genuine **syntax** error, which esbuild reports with the file, line and column. The practical consequence is that TypeScript in k6 buys you editor tooling and an optional checking step in CI, not a safety net at run time: - keep a `tsc --noEmit` (or equivalent) step in the pipeline that runs your test sources, because k6 itself will never tell you a type is wrong; - do not treat a green k6 run as evidence that the types are right; - remember that type-only imports and re-exports vanish in the strip, so nothing type-level can influence run-time behaviour. ## Version context Getting TypeScript to run used to require an opt-in compatibility mode. In k6 v2 that is history: stripping is the default behaviour for `.ts` files, and the old mode is deprecated with a warning pointing you back at plain operation. Any guide that tells you to pass a special flag, install Babel, or pre-bundle purely in order to run a `.ts` test file is describing an older k6.
- If k6 never type-checks, what value does writing k6 tests in TypeScript still have?Editor tooling and a separate checking step. Autocomplete and inline errors against the k6 type definitions catch mistakes while you write, and a `tsc --noEmit` job in CI catches the rest. k6 itself will never report a type error, so that job is the only thing enforcing the types.
- Does k6 apply type stripping to imported .ts files as well as the entry script?Yes, file by file, on the same rule. An imported `./helpers.ts` gets the fallback if Sobek cannot parse it; a `./helpers.js` containing annotations does not. Because k6 does no extension guessing, you must write the specifier as `./helpers.ts` exactly.
saying these in an interview costs you the question
- Thinks k6 type-checks scripts and fails on type errors
- Expects k6 to read tsconfig.json compiler options
- Says a compatibility-mode flag is needed to run .ts files
- Assumes esbuild also down-levels modern syntax for Sobek
- Believes renaming a .ts file to .js is harmless