uni-app 中 vue3 + setup + ts + pinia 调用 stores 时,类型推导的内容错误,但实际执行正确
uni-app 中 vue3 + setup + ts + pinia 调用 stores 时,类型推导的内容错误,但实际执行正确
示例代码:
import { ref } from 'vue';
import { defineStore } from 'pinia';
export const useUserInfoStore = defineStore('userInfoStore', () => {
const authTokenData = ref();
function $reset() {
authTokenData.value = '';
}
return {
authTokenData,
$reset,
};
});
<script setup lang="ts">
import { ref } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import { useUserInfoStore } from '@/stores/userInfoStore';
const userInfoStore = useUserInfoStore();
userInfoStore.authTokenData = '无可用网络连接1';
...
</script>
...
const userInfoStore = useUserInfoStore();
async function request<T = any>(options: HttpOptionsNew) {
userInfoStore.authTokenData = '无可用网络连接2';
...
操作步骤:
无特殊操作,正常 pinia 创建和调用
预期结果:
编辑器正常提示,编译运行正常。
实际结果:
编辑器类型推导提示不能赋值,需要加 .value,但是实际编译运行正常
| 项目信息 | 详细信息 |
|---|---|
| 产品分类 | uniapp/小程序/微信 |
| PC开发环境操作系统 | Windows |
| PC开发环境操作系统版本号 | windows 10 |
| HBuilderX类型 | 正式 |
| HBuilderX版本号 | 3.99 |
| 第三方开发者工具版本号 | 1.06 |
| 基础库版本号 | 3.3.1 |
| 项目创建方式 | HBuilderX |

bug描述:
编辑器类型推导 userInfoStore.authTokenData 提示类型错误,需要加 .value,但是按照语法肯定不能加。
然而实际可以通过编译,输出正常。
更多关于uni-app 中 vue3 + setup + ts + pinia 调用 stores 时,类型推导的内容错误,但实际执行正确的实战教程也可以访问 https://www.itying.com/category-93-b0.html
HBuilderX 4.02.2024030621-alpha 已修复。
更多关于uni-app 中 vue3 + setup + ts + pinia 调用 stores 时,类型推导的内容错误,但实际执行正确的实战教程也可以访问 https://www.itying.com/category-93-b0.html
感谢反馈,还提供了复现代码,接下来我看一下这个问题
更新:
我分别使用最先版本的 hbuilderx 和 vscode 跑你提供的代码,唯一的改动是给 authTokenData 默认复制 ‘’ 空字符串。
整体运行和测试,没有遇到编辑器爆红的情况,也欢迎你提供复现工程,复现工程包含对应的 npm 依赖。或者升级到最新正式版、Alpha 版本来验证。
也环境直接给我私信、评论补充更多信息
非常感谢您的热情回复 ! 这个问题我也反馈到了咱 BUG 系统。现在问题已经被确认。
BUG 原因分类:测试例覆盖不全 BUG 详细原因:uniapp项目安装了三方node_modules,依赖了vue,且vue版本和内置vue版本不匹配,导致类型冲突 解决方案:治根 修复方案简述:1. 内置vue库区分开vue2和3 2. 相关引用vue的库也分别区分开,如pinia 3. 已经内置的库类型一律使用内置的库文件的类型 修复方案的测试力度:常见情况测试 测试例和自动化测试脚本:已补测试例和自动化测试脚本 相关模块:本模块是独立模块,改动不涉及其他模块 举一反三:是,vue类型不匹配导致pinia类型推导失败,从而导致pinia类型提示不对
您看还需要我配合做什么?
回复 Medal: 哦哦,原来如此。这样的话就等待后续发版了,后续 hbuidlerx 升级时候更新日志会有体现,如果还有问题,欢迎继续反馈
回复 Medal: issues 地址可以发一下吗?我补充到这个问题的解决方案里
另外还有这个问题,一直挂在哪里,没有进度,不知道您负不负责~ https://issues.dcloud.net.cn/pages/issues/detail?id=576
这个如果是我操作错误,也请官方明确。
删除最新回复了?
我用4.01试了下仍然bug
回复 zZZ1Ma: 因为 是其他HBX的bug产生的上游报错,导致还没解析到这个报错,就没提示,我没细看以为没问题了。所以是我测试错误,删除结论了 :)
如果是我操作问题,还请大家帮忙指出
应该是BUG,改用options语法可行,composition语法则不行
用这个demo试试https://stackblitz.com/github/piniajs/example-vue-3-vite?file=README.md,新增两个不同语法的模块
回复 zZZ1Ma: 非常感谢!
回复 Medal: 邀请dcloud官方人员回答试试
回复 zZZ1Ma: 你好,你可以复现这个问题吗?我现在使用最新 alpha 版本没有复现这个问题,欢迎评论我或者私信我,提供更多信息
回复 DCloud_UNI_OttoJi: 看下楼回复,更正下断言写法 app.use(<Pinia & Plugin>pinia) => app.use(pinia as (Pinia & Plugin))
回复 zZZ1Ma: <Pinia & Plugin>pinia 这种断言,运行到微信小程序时报错 Unexpected token
@DCloud_UNI_OttoJi 4.01.2024020211-alpha 新建项目-默认模板-Vue3,以下为复现代码:
// store/index.ts
import { createPinia } from ‘pinia’
export const pinia = createPinia()
// store/module/options
import { defineStore } from ‘pinia’
export const useOptionsStore = defineStore(‘options’, {
state: () => ({
foo: ‘bar’,
timeStamp: 0
})
})
// store/module/composition
import { ref } from ‘vue’
import { defineStore } from ‘pinia’
export const useCompositionStore = defineStore(‘composition’, () => {
//const state = ref({
// foo: ‘bar’,
// token: ‘’,
//})
const state = ref(’’)
return {
state
}
})
// main.ts
import { pinia } from ‘./store’
import type { Plugin} from ‘vue’
import type { Pinia } from ‘pinia’
export function createApp() {
…
BUG1:// 断言以消除类型警告(去除断言即可复现)
app.use(<Pinia & Plugin>pinia)
return { app }
}
// App.vue
import { onLaunch } from ‘@dcloudio/uni-app’
import { useOptionsStore } from ‘./store/module/options’
import { useCompositionStore } from ‘./store/module/composition’
const optionsStore = useOptionsStore()
const compositionStore = useCompositionStore()
onLaunch(e => {
optionsStore.foo = ‘123’ // 指针悬浮‘foo’:(property) foo: string
BUG2: // 指针悬浮‘state’:(property) state: { value: string; [RefSymbol]: true; }
// 不能将类型“string”分配给类型“{ value: string; [RefSymbol]: true; }”。
compositionStore.state = ‘456’
})
而用 Pinia Demo 则无BUG1、BUG2
BUG1
在使用 uni-app 结合 Vue 3、setup、TypeScript 和 Pinia 进行开发时,可能会遇到类型推导错误但实际执行正确的情况。这种情况通常是由于 TypeScript 的类型推断机制不够智能,或者某些类型定义不够明确所导致的。以下是一些可能的原因和解决方案:
1. 确保 Pinia Store 的类型定义正确
首先,确保你的 Pinia Store 已经正确地定义了类型。例如:
// stores/counter.ts
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++;
},
},
});
// 导出类型
export type CounterStore = ReturnType<typeof useCounterStore>;
然后在组件中使用时,确保导入并使用正确的类型:
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter';
import type { CounterStore } from '@/stores/counter';
const counterStore: CounterStore = useCounterStore();
</script>
2. 使用 storeToRefs 进行解构
如果你在 setup 中解构 Pinia Store 的状态,建议使用 storeToRefs 来保持响应性,并且确保类型推导正确:
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
const counterStore = useCounterStore();
const { count } = storeToRefs(counterStore);
</script>
这样可以避免直接解构导致的类型推导问题。
3. 检查 TypeScript 配置
确保你的 tsconfig.json 配置正确,特别是 compilerOptions 中的 strict 选项。启用 strict 模式可以帮助 TypeScript 更好地进行类型检查:
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node",
"target": "esnext",
"module": "esnext",
"lib": ["dom", "esnext"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
4. 使用 as 进行类型断言
如果 TypeScript 的类型推导仍然不正确,你可以使用 as 进行类型断言,明确指定类型:
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter';
import type { CounterStore } from '@/stores/counter';
const counterStore = useCounterStore() as CounterStore;
</script>
这样可以强制 TypeScript 使用你指定的类型,避免类型推导错误。
5. 检查 Pinia 和 Vue 的版本兼容性
确保你使用的 Pinia 和 Vue 3 版本是兼容的。有时版本不兼容也会导致类型推导问题。你可以通过以下命令检查版本:
npm list pinia
npm list vue
如果版本不兼容,建议升级或降级到兼容的版本。
6. 使用 defineComponent 包裹 setup
如果你在 setup 中遇到类型推导问题,可以尝试使用 defineComponent 包裹 setup,这样可以更好地进行类型推导:
<script lang="ts">
import { defineComponent } from 'vue';
import { useCounterStore } from '@/stores/counter';
export default defineComponent({
setup() {
const counterStore = useCounterStore();
return {
counterStore,
};
},
});
</script>


