Vue3电影中后台开发纪实(七):重构为TS

@创建工程

创建空白Vue+TS工程

npm init vue@latest

移植内容

  • [x] src覆盖
  • [x] package.json合并
  • [x] vite.config.js合并
  • [x] src下所有js改名ts
  • [x] 所有vue文件lang=ts

运行起来

npm run dev

@检查TS语法

执行类型检查

npm run type-check

Found 313 errors in 30 files.

允许隐式any

"noImplicitAny": false,

@.ts件重构细节

useScroll.ts

type Scrollable = window | HTMLElement
export default function (target:Scrollable = window, dataRef = null) {...}
const offset = (target as HTMLElement).scrollTop - y;

router/index.ts

路由表类型分配错误

import { createRouter, createWebHistory, type RouteRecordRaw } from "vue-router";
const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: ([...publicRoutes] as readonly RouteRecordRaw[]),
});

类型“unknown”上不存在属性“user”。ts(2339)

interface StoreState {
    user:User,
    token:string
}
console.log("beforeEach",(store.state as StoreState).user);

类型“{ path: string; name: string; meta: { menuIndex: string; adminRequired: boolean; }; component: () => Promise<typeof import(“d:/GZH5/H5-2207/manager_2207/movie-manats-2207/src/views/cinema/HotCity.vue”)>; }”的参数不能赋给类型“RouteRecordName”的参数。ts(2345)

import { type RouteRecordName } from "vue-router";
  adminRoutes.forEach(r => {
     // 未挂载就挂载
     if (!router.hasRoute(<RouteRecordName><unknown>r)) {
        router.addRoute(r);
        console.log(`挂载${r}完毕`);
     } else {
        console.log(`${r}已挂载`);
     }
  });

store/index.ts

类型“unknown”上不存在属性“user”。ts(2339)

   getters: {
      isAdmin(state){
         return (state as StoreState).user && (state as StoreState).user.admin
      }
   },

不能将类型“{ namespaced: boolean; state(): { content: any; }; getters: {}; mutations: { setObj(state: any, content: any): void; }; actions: { fetchContent({ commit, sate }: { commit: any; sate: any; }, arg: any): Promise<void>; }; }”分配给类型“Module<any,unknown>”。

/* 子模块 */
modules: {
  demoModule: (demoModule as any),
},

Found 73 errors in 10 files.

@.vue文件重构细节

NotFound.vue

类型“string | string[]”上不存在属性“join”。
类型“string”上不存在属性“join”。ts(2339)

<p>/{{ ($route.params.pm as string[]).join("/") }}</p>

Playing.vue

类型“{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & Omit<Readonly<ExtractPropTypes<{}>> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>; … 10 more …; $watch<T extends string | ((…args: any) => any)>(source: T, cb: T extends (…args: any) => infer R ? (args_0: R, args_1: R) => …”上不存在属性“$store”。ts(2339)

 <!-- 不是管理员就隐藏之 -->
 <el-button
    v-admin
    class="opBtn"
    type="danger"
    @click="patchDelete">
    <el-icon><Close /></el-icon>&nbsp;删除
 </el-button>

属性“replaceAll”在类型“string”上不存在。是否需要更改目标库? 请尝试将 “lib” 编译器选项更改为“es2021”或更高版本。ts(2550)

找不到名称“console”。是否需要更改目标库? 请尝试更改 “lib” 编译器选项以包括 “dom”。ts(2584)

"lib": ["DOM","ES2021"]

不能将类型“{ msg: string; callback: () => void; }”分配给类型“{ msg: string; callback: () => Promise<void>; }”。
在这些类型中,”callback()” 返回的类型不兼容。ts(2322)

/* 批量删除 */
const patchDelete = () => {
   // 确认删除对话框显示粗来
   dialogMode.value = (dialogModes.patchDelete as any);
   dialogVisible.value = true;
};

Coming.vue

不能将类型“{ msg: string; callback: () => void; }”分配给类型“{ msg: string; callback: () => Promise<void>; }”。
在这些类型中,”callback()” 返回的类型不兼容。ts(2322)

/* 批量删除 */
const patchDelete = () => {
// 确认删除对话框显示粗来
dialogMode.value = (dialogModes.patchDelete as any);
refEpDialog.value.setDialogVisible(true);
};

App.vue

不能将unknown类型分配给string

const currentMenuIndex = computed(():string => {
   const result = (route.meta.menuIndex as string);
   console.log("route=", route);
   console.log("currentMenuIndex=", result);
   return result;
});

EpTable.vue

类型“{}”上不存在属性“prop”。ts(2339)

interface EpTableColConfig {
   prop: string;
   label: string;
   fixed: boolean;
   width: number;
   formatter: any;
   hasSlot: boolean;
   nosort: boolean;
}
const { tableData, pageSize, fixedCol, cols, /* colWidth, */ avgColWidth } = defineProps({
tableData: Array,
pageSize: Number,
fixedCol: Object,
cols: Array<EpTableColConfig>,
avgColWidth: Number,
});

App.vue

const menu = ref(adminMenu as EpMenuItem[])

DynamicLineChart.vue

类型“number”的参数不能赋给类型“string”的参数。ts(2345)

data.push(5000 + parseInt(Math.random() * 5000 + ""));

BtnGroup.vue

类型“unknown”上不存在属性“type”。ts(2339)

interface GroupBtnConfig {
    name: string,
    type: string,
    slotName: string,
    callback: string,
}
const { groupBtns } = defineProps({
groupBtns: Array<GroupBtnConfig>,
});

EpMenuUnit.vue

类型“unknown”上不存在属性“submenu”。ts(2339)

interface EpMenuItem {
    name:string,
    iconName?:string,
    path?:string,
    submenu?:EpMenuItem[]
}
const { activeIndex, menu, parentIndex } = defineProps({
activeIndex: String,
menu: Array<EpMenuItem>,
parentIndex: String,
});

类型“{}”上不存在属性“runtime”。ts(2339)

interface FilmType {
    name:string,
}

interface Film {
    _id:string,
    filmId:string,
    name:string,
    runtime:string,
    grade:string,
    filmType:FilmType,
    premiereAt:number,
    isPresale:number,
    category:string,
    nation:string,
    actors:string,
    poster:string,
    synopsis:string,
}

interface FormUploadPicture {
    name:string,
    url:string,
}

interface FilmForm extends Film {
    category:string[],
    poster:FormUploadPicture[],
    actors:FormUploadPicture[],
}
// 表单数据存储器
const form = reactive<FilmForm>({} as FilmForm);

@排错摘要

找不到模块“@store/index”或其相应的类型声明。ts(2307)

"paths": {
    "@/*": ["./src/*"],
    "@api/*": ["./src/api/*"],
    "@assets/*": ["./src/assets/*"],
    "@components/*": ["./src/components/*"],
    "@demos/*": ["./src/demos/*"],
    "@directives/*": ["./src/directives/*"],
    "@hooks/*": ["./src/hooks/*"],
    "@router/*": ["./src/router/*"],
    "@store/*": ["./src/store/*"],
    "@views/*": ["./src/views/*"]
},

“config.headers”可能为“未定义”。ts(18048)

config.headers!["Authorization"]

“store.state”的类型为“未知”。ts(18046)

config.headers!["Authorization"] = `Bearer ${(store.state as any).token}`;
const { arr: films } = await <doGetResponse>(doGet(`/film/0`) as unknown);

类型“number”的参数不能赋给类型“string”的参数。ts(2345)

var minutesDiffer = parseInt(oddMillis / (60 * 1000) + "");

不能将类型“number”分配给类型“null”。ts(2322)

"strictNullChecks": false,

@env.d.ts

/// <reference types="vite/client" />

// interface CrudFn {
//    (url: string, data: StringAnyMap, config: StringAnyMap): Promise<any>;
// }

interface StringAnyMap {
   [key: string]: any;
}

interface doDeleteData {
   deletedCount: number;
}

interface doPutData {
   modifiedCount: number;
}

interface doPostResult {
   insertedId: string;
}

interface doCrudResponse {
   msg: string;
}

interface User {
   username: string;
   password: string;
   admin: boolean;
}

interface loginResponse extends doCrudResponse {
   users: User[];
   token: string;
}

interface doGetResponse extends doCrudResponse {
   arr: Array[any];
}

interface doDeleteResponse extends doCrudResponse {
   data: doDeleteData;
}

interface doPutResponse extends doCrudResponse {
   data: doPutData;
}

interface doPostResponse extends doCrudResponse {
   result: doPostResult;
}

type Scrollable = window | HTMLElement;

interface StoreState {
   count: number;
   user: User;
   token: string;
}

interface EpTableColConfig {
   prop: string;
   label: string;
   fixed?: boolean;
   width?: number;
   formatter?: any;
   hasSlot?: boolean;
   nosort?: boolean;
}

interface GroupBtnConfig {
    name: string,
    type: string,
    slotName: string,
    callback: string,
}

interface EpMenuItem {
    name:string,
    iconName?:string,
    path?:string,
    submenu?:EpMenuItem[]
}

interface FilmType {
    name:string,
}

interface Film {
    _id:string,
    filmId:string,
    name:string,
    runtime:string,
    grade:string,
    filmType:FilmType,
    premiereAt:number,
    isPresale:number,
    category:string,
    nation:string,
    actors:string,
    poster:string,
    synopsis:string,
}

interface FormUploadPicture {
    name:string,
    url:string,
}

interface FilmForm extends Film {
    category:string[],
    poster:FormUploadPicture[],
    actors:FormUploadPicture[],
}

@tsconfig.json

{
   "extends": "@vue/tsconfig/tsconfig.web.json",
   "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
   "compilerOptions": {
      "baseUrl": ".",
      "paths": {
         "@/*": ["./src/*"],
         "@api/*": ["./src/api/*"],
         "@assets/*": ["./src/assets/*"],
         "@components/*": ["./src/components/*"],
         "@demos/*": ["./src/demos/*"],
         "@directives/*": ["./src/directives/*"],
         "@hooks/*": ["./src/hooks/*"],
         "@router/*": ["./src/router/*"],
         "@store/*": ["./src/store/*"],
         "@views/*": ["./src/views/*"]
      },
      "noImplicitAny": false,
      "strictNullChecks": false,
      "lib": ["DOM","ES2021"]
   },

   "references": [
      {
         "path": "./tsconfig.config.json"
      }
   ]
}
© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容