TypeScript

Types arrive with the subpath: props, emits, the instance and the tokens. Plus web-types for JetBrains, which almost nobody knows about.

Machine-translated, not yet reviewed. Read the original

The package is written in TypeScript, and the types are not collected into one shared .d.ts: every subpath has its own. Import a component and you get its types without pulling in the declarations of all the others.

What a component subpath exports

ts
import {
  GrButton,
  type GrButtonProps,
  type GrButtonInstance,
  type GrButtonTone,
} from '@feugene/granularity/components/GrButton'

The naming is the same for every component, which is more useful than a list:

TypeWhat it describes
GrXPropsThe component’s props
GrXEmitsEvents — where there are any
GrXInstanceThe public instance: what the component exposed
GrXSize, GrXTone, GrXVariantThe allowed values of the matching prop
GrXConfigurablePropsThe subset of props configurable through GrConfigProvider
grXConfig, grXSafelistValues rather than types: the component’s config and its UnoCSS safelist

GrXInstance comes in handy wherever the component is addressed by reference:

vue
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import type { GrDataTableInstance } from '@feugene/granularity/components/GrDataTable'

const table = useTemplateRef<GrDataTableInstance>('table')
</script>

Composite components also hand out the types of their data — for the table that is GrDataColumn, GrDataTableRowKey, GrDataTableSortDir and everything else you would otherwise describe at home and keep in sync by hand.

Types unrelated to components

  • @feugene/granularity/tokens — the token reference as typed data: grFoundationTokens, grThemeTokens, grComponentTokens, grDerivedTokens and the types for them. The source is the same tokens/*.json the CSS is generated from, so they cannot drift from the real values.
  • @feugene/granularity/directives — the directives together with the types of their arguments.
  • @feugene/granularity/fileValidation — file validation rules as a separate module: there the types are the main value rather than a side effect.

The token reference is deliberately not re-exported from the package root. It is data for documentation and tooling; an application does not need it at runtime, and dragging it into the main bundle would break the very promise all of this exists for.

JetBrains: completion out of the box

The package builds and publishes web-types.json — a format the JetBrains IDEs read by themselves. Nothing needs configuring: after installation WebStorm, PhpStorm and IDEA know the package’s components in templates, their props, their defaults and their descriptions.

The file is declared in package.json through the web-types field and sits in dist. It is a ready capability that, until this page, was mentioned nowhere.

VS Code and the rest

EnvironmentWhat works
VS Code + Vue (Official)Types from .d.ts and descriptions from JSDoc — that is, everything except dedicated snippets
Zed, NeovimThrough the same Vue LSP, nothing to configure
JetBrainsPlus web-types.json

Project setup

The package requires nothing specific, but two points save an evening:

  1. "moduleResolution": "bundler" (or "node16") in tsconfig.json. With "node" TypeScript does not read the exports field and will not find the subpath types — a component import is flagged as an error even though it builds.
  2. vue-tsc instead of tsc for checking templates. The package types its slots and events, and without vue-tsc that part is not checked at all.

If the types are “not found” specifically on a subpath while the root imports fine, it is almost always the first point; the case with the compiler’s own message is worked through on the troubleshooting page.

Last reviewed: 2026-09-01