Summary
When a function parameter is a destructured object with an inline type annotation and a default value, dtsx emits invalid TypeScript in the .d.ts output. The emitted file fails to parse with error TS1138: Parameter declaration expected.
Minimal repro
// src/index.ts
export function f(
argv: string[] = [],
{
run = true,
exitOnError = false,
}: { run?: boolean, exitOnError?: boolean } = {},
): Promise<void> {
return Promise.resolve()
}Expected .d.ts
export declare function f(
argv?: string[],
options?: { run?: boolean, exitOnError?: boolean },
): Promise<void>;(or any other valid form — e.g. { run, exitOnError }?: { ... })
Actual .d.ts (broken)
export declare function f(argv?: string[], }: { run?: boolean, exitOnError?: boolean } = {},: unknown): Promise<void>;Note the ,: unknown): — dtsx appears to emit : unknown as a placeholder for a parameter name it couldn't synthesize for the destructured arg, but keeps the trailing comma + return type, producing a sequence (,: unknown):) that TypeScript can't parse.
Real-world hit
This was the cause of @stacksjs/clapp@0.2.3's broken published dist/CLI.d.ts(72,50) — see stacksjs/clapp@3800823 for the source-side workaround Chris had to apply. Every consumer of @stacksjs/clapp@0.2.3 (transitive or direct) hit error TS1138: Parameter declaration expected. at compile time.
The workaround required rewriting the source signature from:
async parse(
argv: string[] = processArgs,
{ run = true, exitOnError = false }: { run?: boolean, exitOnError?: boolean } = {},
): Promise<ParsedArgv>to:
async parse(
argv: string[] = processArgs,
options: ParseOptions = {},
): Promise<ParsedArgv> {
let { run = true, exitOnError = false } = options
// …
}The pattern that breaks is well-formed and common in modern TypeScript — would be good to fix at the dtsx layer so consumers don't have to refactor source to dodge it.
Environment
- dtsx: latest (via
bun-plugin-dtsx@0.9.x) - bun: 1.3.13