knip icon indicating copy to clipboard operation
knip copied to clipboard

Marked as unused if used only in Vue <template>

Open crystalfp opened this issue 1 year ago • 2 comments
trafficstars

I have a typescript file that export a function used only in the <template> part of a .vue file like this:

<script setup lang="ts">
import {humanFormat} from "@/services/HumanFormat";
</script>
<template>
      <div>{{ `Isosurface value (${humanFormat(value)})` }}</div>
</template>

Knip wrongly marks the HumanFormat.ts file as unused.

Maybe simply adding a list in the knip.json configuration with files that are used ("Trust me these files are used") could help reduce the noise on the output.

knip 5.11.0

Thanks! mario

crystalfp avatar May 02 '24 05:05 crystalfp

The named import of humanFormat is enough for Knip to consider it referenced/used. So something else might be the culprit here, such as the way the vue file is imported, or the path aliases. So I'd need a proper reproduction to look into it and say something more useful about this.

webpro avatar May 02 '24 08:05 webpro

Hello,

May be an issue with the tsconfig.json configuration created by https://github.com/vuejs/create-vue

The alias path are in tsconfig.app.json and not in the tsconfig.json

  • tsconfig.json :
{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    }
  ]
}
  • tsconfig.app.json
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/**/*.json"],
  "exclude": ["src/**/__tests__/*"],
  "compilerOptions": {
    "composite": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
}

Repro : https://stackblitz.com/edit/vitejs-vite-dpq56w?file=tsconfig.app.json

❯ npx knip

Analyzing workspace ....
Unused files (2)
src/vite-env.d.ts
src/components/HelloWorld.vue
Unresolved imports (1)
@/components/HelloWorld.vue  src/App.vue:1:23

Regards

Mathieu

messenjer avatar May 07 '24 11:05 messenjer

Thanks Mathieu! Repros are great 🙏

There's two different potential solutions to this.

  1. Add knip.json with the same paths:
{
  "paths": {
    "@/*": ["./src/*"]
  }
}
  1. Use knip --tsConfig tsconfig.app.json

With that, I'm going to close issue.

webpro avatar May 10 '24 06:05 webpro

Nothing changed unfortunately. Added the "path" entry to knip.json and executed knip with --tsConfig BTW, tsconfig.json already contains the "path" entry.

crystalfp avatar May 10 '24 12:05 crystalfp

Without a minimal reproduction like @messenjer provided there isn't much to look for me.

webpro avatar May 10 '24 13:05 webpro

@webpro Here is a minimal reproduction. The vue project has been generated with npm create vue@latest. Rename the attached zip file unused.txt to unused.zip and unzip it. This creates the vue-project directory. Then do:

cd vue-project
npm install
knip

You will see that the file src/HumanFormat.ts has been marked as unused, but it is imported in HelloWorld.vue component where its exported routine is used only in the <template> section.

Thanks for your patience! mario

crystalfp avatar Jul 05 '24 06:07 crystalfp

$ knip --version
5.24.1

on Windows

crystalfp avatar Jul 05 '24 06:07 crystalfp

Typo?

<script setup lang="ts">
import { numanFormat } from '../HumanFormat.ts';
</script>

webpro avatar Jul 05 '24 07:07 webpro

Opps, yes.

<script setup lang="ts">
import { humanFormat } from '../HumanFormat.ts';
</script>

So the reproduction failed. I should add more pieces from the original project...

crystalfp avatar Jul 05 '24 07:07 crystalfp

Red face. Have found why this file ("@/services/HumanFormat") is accounted as unused by knip. Because it is only used by components that are loaded dynamically (with something like: defineAsyncComponent(import(components/ui/${ui}.vue) and thus considered unused. If only knip had a way to manually mark files as used even if they cannot be found by knip! Anyway, thanks for the patience and continue with this useful tool!

crystalfp avatar Jul 15 '24 17:07 crystalfp

Ah yes, indeed dynamic import specifiers like import("components/ui/${ui}.vue") are not supported. They might be in the future, though.

There's a few options I can think of:

  • Add such files as entry files using something like entry: ["components/ui/*.vue"] - entry files are always "used"
  • Remove them files from the project files, e.g. project: ["!components/ui/*.vue"]

webpro avatar Jul 15 '24 17:07 webpro