Vize

Type & Script Rules

Type rules use the TypeScript checker when semantic information is needed. Vize reads the same project shape that TypeScript reads from tsconfig.json, so shared ambient names should come from compilerOptions.types, project references, or declaration files.

Script rules are Patina rules for Composition API and Vapor-oriented code. They focus on patterns that are hard to compile efficiently or hard to reason about in Vapor mode.

Type-aware linting is opt-in. Enable it with linter.typeAware: true, vize lint --type-aware, or by explicitly enabling a type/* rule. type/no-reactivity-loss can be enabled directly with vize lint --strict-reactivity. If Corsa cannot be started, Patina reports type/corsa-runtime and skips the checker-backed rule pass instead of silently dropping the configured rules.

--type-aware uses the same Corsa executable resolution as vize check; configure typeChecker.corsaPath when the project needs an explicit tsgo or Corsa binary. Defaults stay zero-cost: Patina does not parse SFCs for checker-backed linting or start Corsa unless the flag, linter.typeAware, or an explicitly enabled type/* rule opts in.

export default defineConfig({
  linter: { typeAware: true },
});

type/require-typed-props

Requires defineProps to be typed instead of using a runtime array declaration.

Default severity: warning Presets: happy-path, nuxt, opinionated

Bad:

<script setup lang="ts">
const props = defineProps(["label", "count"]);
</script>

Good:

<script setup lang="ts">
const props = defineProps<{
  label: string;
  count: number;
}>();
</script>

type/require-typed-emits

Requires defineEmits to describe the emitted event payloads.

Default severity: warning Presets: happy-path, nuxt, opinionated

Bad:

<script setup lang="ts">
const emit = defineEmits(["save"]);

emit("save", form.value);
</script>

Good:

<script setup lang="ts">
const emit = defineEmits<{
  save: [payload: FormValue];
}>();

emit("save", form.value);
</script>

type/no-unsafe-template-binding

Reports template bindings that resolve to unsafe values such as any. The rule is checker-backed, so it follows imported types and project configuration.

Default severity: warning Presets: nuxt, opinionated

Bad:

<script setup lang="ts">
const payload: any = await loadPayload();
</script>

<template>
  <p>{{ payload.title }}</p>
</template>

Good:

<script setup lang="ts">
type Payload = { title: string };

const payload = await loadPayload<Payload>();
</script>

<template>
  <p>{{ payload.title }}</p>
</template>

type/no-floating-promises

Reports promises that are created but not awaited, returned, or intentionally handled. The check covers both <script> and template expressions.

Default severity: warning Presets: nuxt, opinionated

Bad:

<script setup lang="ts">
function submit() {
  saveForm(form.value);
}
</script>

<template>
  <button @click="saveForm(form)">Save</button>
  <p>{{ loadPreview() }}</p>
</template>

Good:

<script setup lang="ts">
type Preview = { title: string };

async function submit() {
  await saveForm(form.value);
}

const preview = ref<Preview | null>(null);

async function loadPreviewIntoState() {
  preview.value = await loadPreview();
}
</script>

<template>
  <button @click="void submit()">Save</button>
  <button @click="void loadPreviewIntoState()">Preview</button>
  <PreviewPanel v-if="preview" :preview="preview" />
</template>

type/no-reactivity-loss

Reports plain snapshots of reactive values that are used across flows. The rule also runs when vize lint --strict-reactivity is enabled.

Default severity: warning Presets: nuxt, opinionated

Bad:

<script setup lang="ts">
const props = defineProps<{ item: { name: string } }>();
const item = props.item;
</script>

Good:

<script setup lang="ts">
const props = defineProps<{ item: { name: string } }>();
const item = toRef(props, "item");
</script>

Checker Configuration

The type-aware rules do not need a separate Vize globals field for TypeScript names. Prefer TypeScript-native configuration:

Bad:

export default {
  globals: ["definePageMeta", "process"],
};

Good:

{
  "compilerOptions": {
    "types": ["node", "nuxt/app"]
  }
}

script/no-options-api

Reports Options API component definitions in Vapor-oriented presets.

Default severity: error Presets: nuxt, opinionated

Bad:

<script lang="ts">
export default {
  data() {
    return { count: 0 };
  },
};
</script>

Good:

<script setup lang="ts" vapor>
const count = ref(0);
</script>

script/no-next-tick

Reports nextTick() in Vapor-oriented components. Prefer direct refs, lifecycle hooks, or state flow that does not depend on the next DOM flush.

Default severity: error Presets: nuxt, opinionated

Bad:

<script setup lang="ts" vapor>
await nextTick();
input.value?.focus();
</script>

Good:

<script setup lang="ts" vapor>
const input = useTemplateRef<HTMLInputElement>("input");

onMounted(() => {
  input.value?.focus();
});
</script>

script/no-get-current-instance

Reports getCurrentInstance() in Vapor-oriented components. It reaches into runtime internals that Vapor cannot safely optimize.

Default severity: error Presets: nuxt, opinionated

Bad:

<script setup lang="ts" vapor>
const instance = getCurrentInstance();
const app = instance?.appContext.app;
</script>

Good:

<script setup lang="ts" vapor>
const appConfig = useAppConfig();
</script>