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/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>