johnsoncodehk / johnsoncodehk/typescript-native-bridge

vue-tsc emits Button.vue.d.vue.ts instead of Button.vue.d.ts

Open
#63 1 comment 1 reaction 2 assignees View on GitHub

@johnsoncodehk is already working on this.

Since Aug 22, 2026.

  • #68 by @copilot-swe-agent — closed without merging
Dominant language
JavaScript
Stars
295
Forks
9
PR merge metrics
No merged PRs in 30d

Description

vue-tsc declaration emit produces an invalid duplicated extension when TypeScript is replaced with TNB.

Versions

  • typescript-native-bridge: 6.0.3-bridge.13.tsgo.7.0.2
  • vue-tsc: 3.3.10
  • vue: 3.5.41
  • Node.js: 24.19.0
  • Platform: macOS arm64

Minimal reproduction

package.json:

{
  "private": true,
  "type": "module",
  "devDependencies": {
    "typescript": "npm:typescript-native-bridge@6.0.3-bridge.13.tsgo.7.0.2",
    "vue": "3.5.41",
    "vue-tsc": "3.3.10"
  }
}

tsconfig.json:

{
  "include": ["src/**/*.ts", "src/**/*.vue"],
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "target": "ESNext",
    "strict": true,
    "skipLibCheck": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "rootDir": "src",
    "outDir": "dist"
  }
}

src/components/Button.vue:

<script setup lang="ts">
defineProps<{ disabled?: boolean }>()
</script>

<template>
  <button :disabled="disabled" />
</template>

src/index.ts:

export { default as Button } from "./components/Button.vue"

Run:

pnpm install
pnpm exec vue-tsc -p tsconfig.json --listEmittedFiles

Actual output

TSFILE: .../dist/components/Button.vue.d.vue.ts
TSFILE: .../dist/index.d.ts

dist/index.d.ts contains:

export { default as Button } from "./components/Button.vue";

TypeScript 6.0.3 cannot resolve that export. With moduleResolution: "Bundler", it probes Button.d.vue.ts and Button.vue.d.ts, but not Button.vue.d.vue.ts, resulting in:

error TS2307: Cannot find module './components/Button.vue'
or its corresponding type declarations.

Setting allowArbitraryExtensions explicitly to false does not change the emitted filename.

Expected output

dist/components/Button.vue.d.ts
dist/index.d.ts

Switching only the TypeScript dependency to the official compatibility package:

"typescript": "npm:@typescript/typescript6@6.0.2"

and performing a clean install emits:

TSFILE: .../dist/components/Button.vue.d.ts
TSFILE: .../dist/index.d.ts

The compatibility package uses the stock TypeScript 6.0.3 compiler.

Suspected cause

Volar patches the classic TypeScript declaration-emitter filename handling for registered extra-file extensions such as .vue.

TNB's Program.emit delegates emission to tsgo and returns the Go emitter's output filenames directly. This may bypass Volar's patched filename handling and combine the original .vue suffix with tsgo's .d.vue.ts suffix, producing .vue.d.vue.ts.

This appears separate from #33: emitDeclarationOnly is honored correctly here; only the declaration output filename is wrong.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.