-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Description
Version
3.2.14
Reproduction link
Steps to reproduce
I needed to paste link to separate reproduction repository, because the SFC Playground does not seem to be performing type-checking. It's probably running in transpile-only mode.
I'm not sure whether this is problem with Vue compiler or TypeScript type checking, but there is a difference whether you assign a Ref
const inside <script lang="ts" setup>
directly or via some function's return value.
const titled1 = ref<Titled>()
const titled2 = innerSetup() as Ref<Titled | undefined>
In theory they both have the same type, but Vue compiler treats them differently when used in template like:
<h1 v-if="titled1">{{ titled1.title }}</h1>
<h1 v-if="titled2">{{ titled2.title }}</h1>
The resulting TypeScript is:
(titled1.value)
? (_openBlock(), _createElementBlock("h1", _hoisted_1, _toDisplayString(titled1.value.title), 1 /* TEXT */))
: _createCommentVNode("v-if", true),
(_unref(titled2))
? (_openBlock(), _createElementBlock("h1", _hoisted_2, _toDisplayString(_unref(titled2).title), 1 /* TEXT */))
: _createCommentVNode("v-if", true)
The first conditional is correctly understood by tsc
, but the second one yields error:
src/App.ts:38:79 - error TS2532: Object is possibly 'undefined'.
38 ? (_openBlock(), _createElementBlock("h1", _hoisted_2, _toDisplayString(_unref(titled2).title), 1 /* TEXT */))
~~~~~~~~~~~~~~~
Found 1 error.
Now, this might be a bug of TypeScript, because it should understand that if _unref(titled2)
is truthy then it is an instance of Titled
just like it does for titled1.value
. But whether it's TS bug or not it is a Vue problem. I have found no workaround for this other than using titled2?.title
in the template, but that kills the benefit of the type check.
What is expected?
We should be able to use const a = f() as Ref<Type | undefined>
in template conditions.
What is actually happening?
Compiling template fails.