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

Image 1 Image 2 Image 3

bug描述:

编辑器类型推导 userInfoStore.authTokenData 提示类型错误,需要加 .value,但是按照语法肯定不能加。
然而实际可以通过编译,输出正常。


更多关于uni-app 中 vue3 + setup + ts + pinia 调用 stores 时,类型推导的内容错误,但实际执行正确的实战教程也可以访问 https://www.itying.com/category-93-b0.html

24 回复

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

在使用 uni-app 结合 Vue 3setupTypeScriptPinia 进行开发时,可能会遇到类型推导错误但实际执行正确的情况。这种情况通常是由于 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 的版本兼容性

确保你使用的 PiniaVue 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>
回到顶部