到底要怎样才能在 vue3 的 vue 文件里使用上完整的 TS 语法? 只能用一半可太离谱了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
skypyb
V2EX    Vue.js

到底要怎样才能在 vue3 的 vue 文件里使用上完整的 TS 语法? 只能用一半可太离谱了

  •  
  •   skypyb 2021-03-27 21:1:12 +08:00 6865 次点击
    这是一个创建于 1658 天前的主题,其中的信息可能已经有所发展或是发生改变。

    某一部分特性在 vue 文件里还能用上一点,比如类型约束,IDE 做类型推断也还行。

    但是会有些其他的特性用不了, 比如我遇到这这俩问题。
    一个是接口不能直接在 type='ts' 的 script 块中定义。(试了下类也一样)
    还有就是无法使用类型断言。

    在 .ts 文件里就能用, 在 vue 里就不能用。 你说像是接口这种就算了, 定义在 ts 文件里引进来我还能拿着用 (?其实这也很怪)。 像这种需要做类型断言的地方我就真的是没办法了...

    Unexpected reserved word 'interface' (6:4) 4 | import {NotesView} from '@/api/uinfo-service'; 5 | > 6 | interface Ass { | ^ 7 | asv: string 8 | } 9 | 

     Unexpected token, expected "," (10:29) 8 | props: { 9 | note: { > 10 | type: Object as PropType<NotesView>, | ^ 11 | required: true 12 | } 13 | }, 

    搜遍了各个地方, 没找到相似的例子。我甚至不知道是什么地方出的问题。 版本?插件?配置?
    没办法只能来这求助啦


    下边贴几个文件, 大佬们帮看下呗


    package.json

    { "name": "fev-test", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" }, "dependencies": { "@ant-design/icons-vue": "^6.0.1", "ant-design-vue": "^2.0.0", "axios": "^0.21.1", "babel-plugin-import": "^1.13.3", "compression-webpack-plugin": "^7.1.2", "core-js": "^3.8.3", "script-ext-html-webpack-plugin": "^2.1.5", "vue": "^3.0.5", "vue-class-component": "^8.0.0-rc.1", "vue-loader": "^15.9.6", "vue-loader-v16": "^16.0.0-beta.5.4", "vue-router": "^4.0.3", "vuex": "^4.0.0" }, "devDependencies": { "@types/chai": "^4.2.11", "@types/lodash": "^4.14.161", "@types/mocha": "^5.2.4", "@typescript-eslint/eslint-plugin": "^4.15.0", "@typescript-eslint/parser": "^4.15.0", "@vue/cli-plugin-babel": "~4.5.11", "@vue/cli-plugin-eslint": "~4.5.11", "@vue/cli-plugin-router": "~4.5.11", "@vue/cli-plugin-typescript": "~4.5.11", "@vue/cli-plugin-vuex": "~4.5.11", "@vue/cli-service": "~4.5.11", "@vue/compiler-sfc": "^3.0.5", "@vue/eslint-config-prettier": "^6.0.0", "@vue/eslint-config-typescript": "^7.0.0", "babel-eslint": "^10.1.0", "eslint": "^7.20.0", "eslint-plugin-html": "^6.1.1", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^7.6.0", "less": "^4.1.1", "less-loader": "^7.3.0", "prettier": "^2.2.1", "style-resources-loader": "^1.4.1", "typescript": "~4.1.5", "vue-cli-plugin-style-resources-loader": "~0.1.4", "webpack-bundle-analyzer": "^4.4.0" }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ] } 

    tsconfig.json

    { "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "declaration": true, "jsx": "preserve", "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "skipLibCheck": false, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "suppressImplicitAnyIndexErrors": true, "sourceMap": false, "baseUrl": ".", "rootDir": ".", "types": [ "webpack-env", "chai", "mocha" ], "paths": { "@/*": [ "src/*" ] }, "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "exclude": [ "node_modules", "dist" ] } 

    babel.config.js

    module.exports = { presets: ['@vue/cli-plugin-babel/preset'] }; 

    .eslintrc.js

    module.exports = { root: true, parserOptions: { parser: '@typescript-eslint/parser', }, env: { browser: true, es6: true, node: true, }, plugins: ['vue', '@typescript-eslint/eslint-plugin'], rules: { 'no-unused-vars': 'off', '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/member-delimiter-style': 'off', '@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/class-name-casing': 'off', 'vue/valid-v-slot': 'off', 'vue/experimental-script-setup-vars': 'off', 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', indent: ['off', 4, {SwitchCase: 1}], // 缩进不管 'line-comment-position': [ 'off', {position: 'above', ignorePattern: 'ETC'}, ], // 强制行注释的位置 'vue/no-v-model-argument': 'off', 'vue/no-setup-props-destructure': 'off', 'vue/no-multiple-template-root': 'off', '@typescript-eslint/no-var-requires': 0, 'vue/html-indent': ['warn', 4], quotes: ['error', 'single'], // 使用单引号 }, extends: [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/typescript/recommended', ], overrides: [ { files: [ '**/tests/*.{j,t}s?(x)', '**/tests/**/*.spec.{j,t}s?(x)', '**/tests/*.spec.{j,t}s?(x)', ], env: { mocha: true, }, }, ], }; 

    vue.config.js

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') .BundleAnalyzerPlugin const IS_DEV = process.env.NODE_ENV !== 'production' /** * @todo 开发环境配置 * 某些实用工具,plugins 和 loaders 都只能在构建生产环境时才有用 * 在开发时使用 UglifyJsPlugin 来压缩和修改代码是没有意义的,不压缩 */ const DEVELOPMENT = webpackCOnfig=> { /** * @todo 启用 eval-source-map 更好的测试 * 每个模块使用 eval() 执行,并且 source map 转换为 DataUrl 后添加到 eval() 中。 * 初始化 source map 时比较慢,但是会在重新构建时提供比较快的速度,并且生成实际的文件。 * 行数能够正确映射,因为会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map 。 */ webpackConfig.store.set('devtool', 'eval-source-map') webpackConfig.plugin('html').tap(([options]) => [ Object.assign(options, { minify: false, chunksSortMode: 'none' }) ]) // webpackConfig.plugin('BundleAnalyzerPlugin').use(BundleAnalyzerPlugin) return webpackConfig } /** * @todo 生产环境配置 * 每个额外的 loader/plugin 都有启动时间。尽量少使用不同的工具 */ const PRODUCTION = webpackCOnfig=> { /** * @todo 不需要启用 source-map,去除 console 的情况下 source-map 根本没用,还浪费大量时间和空间 * 详情见: https://webpack.js.org/configuration/devtool/#devtool */ webpackConfig.store.set('devtool', '') webpackConfig.plugin('html').tap(([options]) => [ Object.assign(options, { minify: { removeComments: true, removeCommentsFromCDATA: true, collapseWhitespace: true, conservativeCollapse: false, collapseInlineTagWhitespace: true, collapseBooleanAttributes: true, removeRedundantAttributes: true, removeAttributeQuotes: false, removeEmptyAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, useShortDoctype: true, minifyJS: true, minifyCSS: true }, cache: true, // 仅在文件被更改时发出文件 hash: true, // true 则将唯一的 webpack 编译哈希值附加到所有包含的脚本和 CSS 文件中,这对于清除缓存很有用 scriptLoading: 'defer', // 现代浏览器支持非阻塞 Javascript 加载('defer'),以提高页面启动性能。 inject: true, // true 所有 Javascript 资源都将放置在 body 元素的底部 chunksSortMode: 'none' }) ]) return webpackConfig } module.exports = { publicPath: '/', css: { loaderOptions: { less: { sourceMap: IS_DEV, lessOptions: { JavascriptEnabled: true } } } }, devServer: { proxy: 'http://10.10.10.115:8002' }, pluginOptions: { /** 全局加载 lss 的 webpack 插件 */ 'style-resources-loader': { preProcessor: 'less', patterns: ['./src/styles/index.less'] } }, /** * @description 去掉 console 信息 * config.optimization.minimizer[0].options.terserOptions.compress.drop_cOnsole= true; * html-webpack-plugin 插件配置详情见 https://github.com/jantimon/html-webpack-plugin#options */ configureWebpack: cOnfig=> { config.optimization = { splitChunks: { chunks: 'all', minSize: 3000, // (默认值:30000 )块的最小大小。 minChunks: 1, //(默认值:1 )在拆分之前共享模块的最小块数 maxAsyncRequests: 5, //(默认值为 5 )按需加载时并行请求的最大数量 maxInitialRequests: 6, // (默认值为 3 )入口点的最大并行请求数 automaticNameDelimiter: '-', name: true, cacheGroups: { lodash: { name: 'lodash', test: /[\\/]node_modules[\\/]lodash[\\/]/, priority: 20 }, vue: { name: 'vue', test: /[\\/]node_modules[\\/]vue[\\/]/ }, vuex: { name: 'vuex', test: /[\\/]node_modules[\\/]vuex[\\/]/ }, 'vuex-presistedstate': { name: 'vuex-presistedstate', test: /[\\/]node_modules[\\/]vuex-presistedstate[\\/]/ }, 'vue-router': { name: 'vue-router', test: /[\\/]node_modules[\\/]vue-router[\\/]/ }, 'ant-design-vue': { name: 'ant-design-vue', test: /[\\/]node_modules[\\/]ant-design-vue[\\/]/ }, moment: { name: 'moment', test: /[\\/]node_modules[\\/]moment[\\/]/, priority: 40 } } } } }, chainWebpack: cOnfig=> { config.resolve.symlinks(true) if (process.env.use_analyzer) { config.plugin('webpack-bundle-analyzer').use(BundleAnalyzerPlugin) } IS_DEV ? DEVELOPMENT(config) : PRODUCTION(config) }, productionSourceMap: false, lintOnSave: true } 
    24 条回复    2021-03-29 16:26:32 +08:00
    iold
        1
    iold  
       2021-03-27 21:52:12 +08:00
    你应该需要告诉 ts, *.vue 也是 ts 文件, ts 配置里 include 一下 ts 存在哪些文件后缀文件里. 例如 "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
    skypyb
        2
    skypyb  
    OP
       2021-03-27 22:00:59 +08:00
    @iold 刚按照你说的试了下, 仍然不行。 其实是可以在 vue 里用 ts,也配置过了 shims-vue.d.ts ,只是有不少莫名其妙的问题 (比如我上边说的)。
    cereschen
        3
    cereschen  
       2021-03-27 22:45:45 +08:00
    你这个报错是哪个服务报错的 发完整一点
    shakukansp
        4
    shakukansp  
       2021-03-28 00:31:37 +08:00
    lang="ts"
    EPr2hh6LADQWqRVH
        5
    EPr2hh6LADQWqRVH  
       2021-03-28 00:36:43 +08:00
    Vue 和 TypeScript 不兼容的, 只能是主要逻辑单独写在外面的 ts 文件里,vue 只做引用调用。
    想要 vue 里面使用 ts, 太难受了,yyx 不支持。
    einq7
        6
    einq7  
       2021-03-28 00:40:09 +08:00 via iPhone
    @avastms 请问 yyx 是什么
    ShareDuck
        7
    ShareDuck  
       2021-03-28 01:27:46 +08:00 via Android
    @einq7 是指作者吧。
    ruoxie
        8
    ruoxie  
       2021-03-28 02:01:06 +08:00
    直接 tsx 不香吗?写 template 没提示,还不如不用 TS

    https://github.com/lowcoding/lowcode-vscode/blob/vite2/webview-vue-webpack/src/views/snippet/Detail/index.tsx

    写一个 vscode 插件 webview 部分的时候分别用 react 跟 vue3 撸了一次,简直不要太像
    Rocketer
        9
    Rocketer  
       2021-03-28 04:50:52 +08:00 via iPhone   1
    个人感觉因为 Vue 定位于简单,所以就用最简单的 JS,这是匹配的。

    想用 TS,就最好整体升级,用 React 或者 Angular 。非得用 TS 写 Vue,有种用专业咖啡机做速溶咖啡的感觉,没必要,也没什么好的效果。
    ericls
        10
    ericls  
       2021-03-28 04:52:53 +08:00 via iPhone   1
    这就是我所说的 用做框架的思想做语言 肯定会出问题
    Zzzz77
        11
    Zzzz77  
       2021-03-28 07:14:40 +08:00 via Android   3
    首先 vue3 绝对绝对绝对是支持 ts 的,上面说不兼容的几位朋友应该是对 vue 并不太了解。
    回到楼主的问题,第一点,script 标签应该是<script lang="ts">,而不是 type="ts",我不确定是不是你的笔误。
    如果排除这一点,其实以上信息很难看出问题出在哪,我只能给几个建议:
    一,如果方便的话,可以贴出仓库地址,大家可以帮你检查问题出在哪
    二,去看看一些 vue3 + ts 的案例,看看区别在哪里,这种案例 github 一搜一堆,我前段时间也在 v 站上发过一个 vue3 + ts 的项目,你也可以翻我的主题看看
    三,最简单有效的办法,直接用 cli 生成一个 vue3 + ts 的项目模板,对比检查问题出在什么地方

    顺带一提,上面有朋友认为写 template 没提示,还不如不用 TS,个人不太认同,template 是可以通过 ide 插件(如 vscode )支持 ts 提示的,至于 template 和 tsx 哪个好,就见仁见智了~
    iold
        12
    iold  
       2021-03-28 08:30:52 +08:00 via iPhone
    @skypyb #2 你用 cli 生成个 vue3+ts 的项目做对比。
    dumbass
        13
    dumbass  
       2021-03-28 10:09:11 +08:00 via iPhone
    vue2 + composition-api + ts 写起来也蛮香的
    solos
        14
    solos  
       2021-03-28 10:56:15 +08:00
    建议换 angular
    tolking
        15
    tolking  
       2021-03-28 11:55:18 +08:00
    vscode + vetur 没有遇到这些问题,模版的提示据说要等到 setup 稳定后增加。毕竟不是标准的 ts,需要通过 ide 插件辅助支持。
    Cbdy
        16
    Cbdy  
       2021-03-28 12:07:39 +08:00 via Android
    应该不行
    beginor
        17
    beginor  
       2021-03-28 12:40:20 +08:00 via Android
    要体验完整的 ts 支持, 建议试试 angular,ng 11 默认开启严格模式, 真是强迫症的福音!

    另外 react 也不错, tsx 有特供的 ts 支持!

    为啥非得在 vue 上吊死?
    suzic
        18
    suzic  
       2021-03-28 12:50:38 +08:00 via Android
    我们就是那样用的,没碰到楼主说的问题。建议楼主检查下是不是 type='ts'的原因,正确的写法是"lang=ts"
    emilll
        19
    emilll  
       2021-03-28 18:56:23 +08:00
    楼主写法没错的

    <script lang="ts"gt;</script>

    另外 vue3 推荐使用 volar 插件
    hotsymbol
        20
    hotsymbol  
       2021-03-28 22:11:01 +08:00
    用 Typescript 写 Vue ?是脑子不好使吗?用 React 和 Angular 不能写 Typescript 吗?还是不思进取吗?
    Jaosn
        21
    Jaosn  
       2021-03-29 00:07:22 +08:00   1
    这个帖子给我看乐了,几个回复也十分有趣,比如我楼上这位
    Sparetire
        22
    Sparetire  
       2021-03-29 02:54:13 +08:00 via Android
    建议 Vue3 用 volar, Vue2 用 vetur
    rodrick
        23
    rodrick  
       2021-03-29 11:43:03 +08:00
    不明白 vue 写 ts 怎么就有人觉得能上升到脑子不好了
    xiaoliaoliao
        24
    xiaoliaoliao  
       2021-03-29 16:26:32 +08:00
    推荐 volar 但是这插件也不是很成熟 eslint 没法用,如果需要未使用变量报错可以在 tsconfig 的 compilerOptions 中增加字段"noUnusedLocals": true
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     940 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 22:03 PVG 06:03 LAX 15:03 JFK 18:03
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86