diff --git a/.changeset/flat-bobcats-hang.md b/.changeset/flat-bobcats-hang.md
new file mode 100644
index 0000000..c6b0f9b
--- /dev/null
+++ b/.changeset/flat-bobcats-hang.md
@@ -0,0 +1,5 @@
+---
+"typescript-eslint-parser-for-extra-files": patch
+---
+
+fix: wrong type when d.ts file exists
diff --git a/package.json b/package.json
index 9c45267..7e8aa8f 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"astrojs-compiler-sync": ">=0.3.1",
"svelte2tsx": ">=0.5.20",
"typescript": ">=4.8.4",
- "vue": "^3.2.41"
+ "vue": "^3.2.45"
},
"peerDependenciesMeta": {
"astrojs-compiler-sync": {
diff --git a/src/ts.ts b/src/ts.ts
index 20c9b8e..21fa785 100644
--- a/src/ts.ts
+++ b/src/ts.ts
@@ -85,12 +85,11 @@ export class TSService {
// because it targets a file that does not actually exist.
this.fileWatchCallbacks.get(normalizeFileName(this.tsconfigPath))?.();
}
- getFileNamesIncludingVirtualTSX(
- targetPath,
- this.extraFileExtensions
- ).forEach((vFilePath) => {
- this.fileWatchCallbacks.get(vFilePath)?.();
- });
+ getRefreshTargetFileNames(targetPath, this.extraFileExtensions).forEach(
+ (vFilePath) => {
+ this.fileWatchCallbacks.get(vFilePath)?.();
+ }
+ );
}
const program = this.watch.getProgram().getProgram();
@@ -169,9 +168,18 @@ export class TSService {
results.push(file.path);
}
- return distinctArray(...results).map((result) =>
- toVirtualTSXFileName(result, extraFileExtensions)
- );
+ return distinctArray(...results).map((result) => {
+ if (!isExtra(result, extraFileExtensions)) {
+ return result;
+ }
+
+ if (original.fileExists.call(watchCompilerHost, `${result}.d.ts`)) {
+ // If the d.ts file exists, respect it and consider the virtual file not to exist.
+ return result;
+ }
+
+ return toVirtualTSXFileName(result, extraFileExtensions);
+ });
};
watchCompilerHost.readFile = (fileName, ...args) => {
const realFileName = toRealFileName(fileName, extraFileExtensions);
@@ -243,11 +251,19 @@ export class TSService {
// It is the file currently being parsed.
return true;
}
- return original.fileExists.call(
- watchCompilerHost,
- toRealFileName(fileName, extraFileExtensions),
- ...args
- );
+ const real = toRealFileName(fileName, extraFileExtensions);
+ if (original.fileExists.call(watchCompilerHost, real, ...args)) {
+ if (real !== fileName) {
+ if (
+ original.fileExists.call(watchCompilerHost, `${real}.d.ts`, ...args)
+ ) {
+ // If the d.ts file exists, respect it and consider the virtual file not to exist.
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
};
// It keeps a callback to mark the parsed file as changed so that it can be reparsed.
@@ -292,25 +308,24 @@ export class TSService {
}
}
-/** If the given filename is a `.vue` file, return a list of filenames containing virtual filename (.vue.tsx). */
-function getFileNamesIncludingVirtualTSX(
+/**
+ * If the given filename is a extra extension file (.vue),
+ * return a list of filenames containing virtual filename (.vue.tsx) and type def filename (.vue.d.ts).
+ */
+function getRefreshTargetFileNames(
fileName: string,
extraFileExtensions: string[]
) {
- for (const extraFileExtension of extraFileExtensions) {
- if (fileName.endsWith(extraFileExtension)) {
- return [`${fileName}.tsx`, fileName];
- }
+ if (isExtra(fileName, extraFileExtensions)) {
+ return [`${fileName}.tsx`, `${fileName}.d.ts`, fileName];
}
return [fileName];
}
/** If the given filename has extra file extensions, returns the real virtual filename. */
function toVirtualTSXFileName(fileName: string, extraFileExtensions: string[]) {
- for (const extraFileExtension of extraFileExtensions) {
- if (fileName.endsWith(extraFileExtension)) {
- return `${fileName}.tsx`;
- }
+ if (isExtra(fileName, extraFileExtensions)) {
+ return `${fileName}.tsx`;
}
return fileName;
}
@@ -325,6 +340,16 @@ function toRealFileName(fileName: string, extraFileExtensions: string[]) {
return fileName;
}
+/** Checks the given filename has extra file extension or not. */
+function isExtra(fileName: string, extraFileExtensions: string[]): boolean {
+ for (const extraFileExtension of extraFileExtensions) {
+ if (fileName.endsWith(extraFileExtension)) {
+ return true;
+ }
+ }
+ return false;
+}
+
function formatDiagnostics(diagnostics: ts.Diagnostic[]) {
return ts.formatDiagnostics(diagnostics, {
getCanonicalFileName: (f) => f,
diff --git a/tests/fixtures/types/vue/vue-script-setup03/component.vue b/tests/fixtures/types/vue/vue-script-setup03/component.vue
new file mode 100644
index 0000000..4e5667d
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup03/component.vue
@@ -0,0 +1,32 @@
+
+
+
+ {{ exposeA }}
+
diff --git a/tests/fixtures/types/vue/vue-script-setup03/source.vue b/tests/fixtures/types/vue/vue-script-setup03/source.vue
new file mode 100644
index 0000000..295a820
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup03/source.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/tests/fixtures/types/vue/vue-script-setup03/types.vue b/tests/fixtures/types/vue/vue-script-setup03/types.vue
new file mode 100644
index 0000000..bf63073
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup03/types.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/tests/fixtures/types/vue/vue-script-setup04/component.vue b/tests/fixtures/types/vue/vue-script-setup04/component.vue
new file mode 100644
index 0000000..4e5667d
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup04/component.vue
@@ -0,0 +1,32 @@
+
+
+
+ {{ exposeA }}
+
diff --git a/tests/fixtures/types/vue/vue-script-setup04/component.vue.d.ts b/tests/fixtures/types/vue/vue-script-setup04/component.vue.d.ts
new file mode 100644
index 0000000..137401d
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup04/component.vue.d.ts
@@ -0,0 +1,64 @@
+/* eslint eslint-comments/no-unlimited-disable: 0, eslint-comments/disable-enable-pair: 0 -- ignore */
+/* eslint-disable -- ignore */
+declare const _default: {
+ new (...args: any[]): {
+ $: import("vue").ComponentInternalInstance;
+ $data: {};
+ $props: Partial<{}> & Omit> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>;
+ $attrs: {
+ [x: string]: unknown;
+ };
+ $refs: {
+ [x: string]: unknown;
+ };
+ $slots: Readonly<{
+ [name: string]: import("vue").Slot | undefined;
+ }>;
+ $root: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase, {}> | null;
+ $parent: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase, {}> | null;
+ $emit: (event: string, ...args: any[]) => void;
+ $el: any;
+ $options: import("vue").ComponentOptionsBase>, {
+ exposeA: any;
+ exposeFn(): {
+ num: () => number;
+ } | null;
+ exposeFn3(): number;
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {}, {}, string> & {
+ beforeCreate?: ((() => void) | (() => void)[]) | undefined;
+ created?: ((() => void) | (() => void)[]) | undefined;
+ beforeMount?: ((() => void) | (() => void)[]) | undefined;
+ mounted?: ((() => void) | (() => void)[]) | undefined;
+ beforeUpdate?: ((() => void) | (() => void)[]) | undefined;
+ updated?: ((() => void) | (() => void)[]) | undefined;
+ activated?: ((() => void) | (() => void)[]) | undefined;
+ deactivated?: ((() => void) | (() => void)[]) | undefined;
+ beforeDestroy?: ((() => void) | (() => void)[]) | undefined;
+ beforeUnmount?: ((() => void) | (() => void)[]) | undefined;
+ destroyed?: ((() => void) | (() => void)[]) | undefined;
+ unmounted?: ((() => void) | (() => void)[]) | undefined;
+ renderTracked?: (((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[]) | undefined;
+ renderTriggered?: (((e: import("vue").DebuggerEvent) => void) | ((e: import("vue").DebuggerEvent) => void)[]) | undefined;
+ errorCaptured?: (((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase, {}> | null, info: string) => boolean | void) | ((err: unknown, instance: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase, {}> | null, info: string) => boolean | void)[]) | undefined;
+ };
+ $forceUpdate: () => void;
+ $nextTick: typeof import("vue").nextTick;
+ $watch any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => any : (...args: any) => any, options?: import("vue").WatchOptions | undefined): import("vue").WatchStopHandle;
+ } & Readonly> & import("vue").ShallowUnwrapRef<{
+ exposeA: any;
+ exposeFn(): {
+ num: () => number;
+ } | null;
+ exposeFn3(): number;
+ }> & {} & import("vue").ComponentCustomProperties & {};
+ __isFragment?: undefined;
+ __isTeleport?: undefined;
+ __isSuspense?: undefined;
+} & import("vue").ComponentOptionsBase>, {
+ exposeA: any;
+ exposeFn(): {
+ num: () => number;
+ } | null;
+ exposeFn3(): number;
+}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {}, {}, string> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
+export default _default;
diff --git a/tests/fixtures/types/vue/vue-script-setup04/source.vue b/tests/fixtures/types/vue/vue-script-setup04/source.vue
new file mode 100644
index 0000000..295a820
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup04/source.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/tests/fixtures/types/vue/vue-script-setup04/types.vue b/tests/fixtures/types/vue/vue-script-setup04/types.vue
new file mode 100644
index 0000000..5da8781
--- /dev/null
+++ b/tests/fixtures/types/vue/vue-script-setup04/types.vue
@@ -0,0 +1,29 @@
+
+
+
+
+