In Vue's language tooling, what does the vueCompilerOptions setting strictTemplates change, and what is checked in templates without it?
answer
- lives in tsconfig.json
- off by default
- turns on checkUnknown options
- unknown props, events, components
basics
~20 sstrictTemplates is a vueCompilerOptions flag in tsconfig.json, off by default. Turning it on enables strictVModel and the checkUnknownProps, Events, Components and Directives checks, so unknown names in templates become errors in vue-tsc and the editor.
solid answer
~40 s`vueCompilerOptions` is a Vue-specific section of `tsconfig.json` read by both `vue-tsc` and the editor tooling. `strictTemplates` defaults to `false`; setting it to `true` turns on `strictVModel` and the four `checkUnknownProps`, `checkUnknownEvents`, `checkUnknownComponents` and `checkUnknownDirectives` options, each of which can also be set on its own. Without them, templates are still type-checked: expressions, the types of declared props you pass, and event handler parameters are all checked. What is lenient is the unknown: a prop the child does not declare is not reported, which suits attribute fallthrough, and an unresolved component name is not an error. With the flags on, those become errors, catching typos in prop names and forgotten component imports at the cost of flagging intentional fallthrough attributes.
code
vue · 12 lines<script setup lang="ts">
import PriceTag from './PriceTag.vue' // declares props { amount: number }
</script>
<template>
<!-- default: no error, 'colour' falls through as an attribute -->
<!-- strictTemplates / checkUnknownProps: error, 'colour' is not a known prop -->
<PriceTag :amount="12" colour="red" />
<!-- error in both modes: a string is not assignable to the number prop -->
<PriceTag :amount="'twelve'" />
</template>go deeper
Remember that templates are type-checked with lang="ts" by default; strictTemplates adds errors for unknown props, events, components and directives.
Explain why the default is lenient, fallthrough attributes and runtime registration, and which five options strictTemplates turns on.
Roll strict template checking into an existing codebase option by option, typing global components and wrappers, and make sure CI checks through the same tsconfig.
Decide how strict component contracts should be across teams, balancing caught typos against the friction of declaring every fallthrough attribute.
## Where Vue's checking options live Both `vue-tsc` and the editor tooling read a Vue-specific section of `tsconfig.json` called **`vueCompilerOptions`**. It sits next to `compilerOptions`, in whichever tsconfig includes the component: ```json { "compilerOptions": { "strict": true }, "vueCompilerOptions": { "strictTemplates": true }, "include": ["src/**/*.ts", "src/**/*.vue"] } ``` Because both tools read the same key, a setting here changes the editor and CI together, provided both use the same tsconfig. ## What strictTemplates switches on `strictTemplates` defaults to `false`. The language tools' schema describes it as enabling strict templates, turning on all the `checkUnknown*` options. In the source, it supplies the default for five options, each of which can be set independently: | Option | Default | With it on | |---|---|---| | `strictVModel` | follows `strictTemplates` | stricter type constraints on `v-model` bindings | | `checkUnknownProps` | follows `strictTemplates` | passing a prop the component does not declare is an error | | `checkUnknownEvents` | follows `strictTemplates` | listening for an event the component does not declare is an error | | `checkUnknownComponents` | follows `strictTemplates` | an unresolved component tag is an error | | `checkUnknownDirectives` | follows `strictTemplates` | an unresolved custom directive is an error | ## What is checked without it The default is not "templates are unchecked". With `lang="ts"`, template expressions are type-checked: - `{{ user.nmae }}` is an error if `user` has no `nmae` property; - `:count="'3'"` is an error if the child declares `count: number`; - an `@update` handler's parameter types come from the child's declared emits. What the defaults skip is reporting on **unknown** names. The tooling deliberately suppresses the TypeScript errors for unknown properties on props objects and for unknown component names, because Vue allows both at runtime: - an undeclared prop becomes a **fallthrough attribute** and lands on the child's root element; - a component can be registered globally at runtime, where static tooling may not see it. ## Trade-offs of turning it on Benefits: - typos in prop and event names are caught, such as `:colour` for a `color` prop; - forgotten imports or registrations surface as unknown components; - component APIs become an enforced contract. Costs: - intentional fallthrough attributes, such as passing `class`-like or `data-*` attributes through a wrapper, need to be declared or typed to avoid errors; - globally registered components and directives must have type declarations so the tooling can resolve them; - turning it on in an existing codebase often produces a burst of errors to fix. A common path is enabling individual options first, for example `checkUnknownComponents`, then moving to `strictTemplates` once the codebase is clean. ## Rolling it out in an existing codebase 1. Run `vue-tsc --noEmit` with `checkUnknownComponents` alone and fix missing imports or add types for global registrations. 2. Add `checkUnknownDirectives` and type any globally registered custom directives. 3. Add `checkUnknownProps` and `checkUnknownEvents`; for wrapper components that forward arbitrary attributes, declare the forwarded props or accept the reported cases deliberately. 4. Replace the individual flags with `strictTemplates: true` once the codebase is clean, so new options it controls are covered too. 5. Make sure the CI type-check reads the same tsconfig, so the rule is enforced and not just shown in editors. ## Related options, briefly - `fallthroughAttributes` (default `false`) adds typed fallthrough attributes; the schema warns it may significantly slow type-checking. - `extensions` (default `['.vue']`) lists which file extensions are treated as SFCs. ## Making sure CI agrees Since the options live in a tsconfig, CI enforces them only if it checks through that tsconfig. A setting in `tsconfig.app.json` does nothing for a CI step that runs against another config, which is a common reason the editor flags unknown props and CI does not.
- Why does Vue's tooling not report unknown props by default?Because at runtime an undeclared prop is not an error: it becomes a fallthrough attribute on the child's root element, a common pattern for wrapper components. Reporting every unknown name would flag valid code, so the default is lenient and teams opt into `checkUnknownProps` or `strictTemplates` when they want component APIs enforced.
- You enable strictTemplates and a globally registered component is reported as unknown. How do you fix it without turning the option off?Give the tooling a type for the global registration, typically by augmenting Vue's global component types in a declaration file so the name resolves to the component's type. Alternatively import the component locally where it is used. Either way the check stays on and the name is known statically.
saying these in an interview costs you the question
- Without strictTemplates, Vue templates are not type-checked at all.
- strictTemplates is enabled by default in vue-tsc.
- vueCompilerOptions are VS Code settings, not tsconfig settings.
- An unknown prop is always a type error, whatever the options.
- The checkUnknown options can only be enabled all together.