最近为负责的一个移动端项目
(基于vue3+ts)
做了ts的类型补充与优化你问为什么要优化?
皆因一开始大家决定使用ts的时候都是一拍脑袋,觉得应该跟上潮流,结果写着写着就要么变成
anyscript
,要么就是直接强行忽略类型检查(啥也看不见),本强迫症看着一堆红色波浪线(错误提示)实在是难受,另外于是就开始了一顿整,边整边记录,虽然也是有一些投鸡取巧
,不过也算是一次经验吧
我保证,以后一定好好写类型声明
😭
首先,更投机取巧的方法:
为不想ts帮你检查的代码的上方增加一行以下代码
arduino
// @ts-ignore*
这样就不会有红色波浪线(忽略了类型检查)
但咱们是有素质的打工人,怎么可以这样!!还是正经搞吧!
首先得知道,哪些文件没有正确进行类型声明
通过运行命令,在控制台输出类型检查结果:
scss
// 需要编译
npm install -g tsc
// 运行以下命令,即可输出未通过类型检查的文件和具体出处
tsc --noEmit
scss
// 仅类型检查
npm install -g vue-tsc
// 运行以下命令,即可输出未通过类型检查的文件和具体出处
vue-tsc --noEmit
具体区别看下文:
- vue-tsc 命令和 tsc 命令都是用于执行 TypeScript 类型检查的工具,但它们的使用场景略有不同。
- tsc 命令:tsc 是 TypeScript 编译器的命令行工具,用于将 TypeScript 代码编译为 JavaScript。它可以执行类型检查,并且还可以将 TypeScript 代码转换为 JavaScript 代码。tsc 命令会根据项目中的 tsconfig.json 文件中的配置进行类型检查和编译
- vue-tsc 命令:vue-tsc 是专门为 Vue 单文件组件(.vue 文件)设计的 TypeScript 类型检查工具。它是对 tsc 命令的封装,可以在检查 Vue 文件时解析其中的
基于js模块文件提供ts类型检查支持,避免引用js模块时类型检查报错
添加.d.ts文件进行声明,.d.ts 文件用于为 JavaScript 代码提供类型声明。下面是一个示例,展示如何使用 .d.ts 文件来为 JavaScript 代码添加类型信息。
假设我们有一个 JavaScript 文件 themeColors.js,其中定义了一个对象 themeColors,它包含了多个属性来表示不同的主题颜色。
arduino
// themeColors.js
const themeColors = {
theme: 'blue',
themeLight: 'lightblue',
themeDark: 'darkblue',
// 其他属性...
};
export default themeColors;
为了为这个 JavaScript 文件添加类型信息,我们可以创建一个 .d.ts 文件,命名为 themeColors.d.ts,并在其中声明一个模块,定义 ThemeColors 接口来描述 themeColors 对象的类型
typescript
// themeColors.d.ts
declare module '@/core/themeColors.js' {
interface ThemeColors {
theme: string;
themeLight: string;
themeDark: string;
// 其他属性...
}
const themeColors: ThemeColors;
export default themeColors;
}
在这个 .d.ts 文件中,我们使用 declare module 来声明一个模块,模块名为 @/core/themeColors.js,并在模块内部定义了一个接口 ThemeColors,描述了 themeColors 对象的类型。然后,我们使用 const 关键字定义了一个常量 themeColors,并将其导出。
现在,我们可以在其他 JavaScript 或 TypeScript 文件中使用 themeColors 对象,并享受类型检查的好处。
javascript
// otherFile.js
import themeColors from '@/core/themeColors.js';
console.log(themeColors.theme); // 输出 'blue'
console.log(themeColors.themeLight); // 输出 'lightblue'
// 其他属性的访问...
通过这种方式,我们可以在 JavaScript 代码中使用 .d.ts 文件提供的类型信息,从而获得更好的代码提示和类型检查
对于interface中定义为动态属性的值,取值为其他指定类型的变量赋值时报类型错误:不能将类型"number | undefined"分配给类型"number"
kotlin
interface Opt {
page?: number
data: string[]
}
// 取值
const res: Opt = {
data: []
}
let num:number = 0
const { page, data } = res
num = page
// 不能将类型"undefined"分配给类型"number"。ts(2322)
// 因为动态类型有可能类型为undefined, 而num变量的类型是number
解决:取值时为动态属性赋默认值
ini
// 为动态属性page设置默认值,则不会抛类型不匹配错误
const { page = 1, data } = res
num = page
类型推断的使用 --- 万能的【as】
typescript
// 场景一、不想重复定义初始值,而又不想为interface的所有属性改为非必填选项(其实有点投机取巧)
export interface ExpressInfo {
"context":string // 内容
"time": string // 时间,原始格式
"status": string //对应的物流状态名称或者高级状态名称
"statusCode": string // 高级物流状态值
"areaCode": string // 行政区域的编码
"areaName": string // 行政区域的名称
"areaCenter": string // 行政区域经纬度
"location": string // 快件当前地点
"areaPinYin": string // 行政区域拼音
}
// 定义一个变量,类型为ExpressInfo ,但由于我有点懒,不想维护两套字段,但又想保留编辑器提示
const data:ExpressInfo = {} as ExpressInfo
// 场景二、使用第三方库的时候缺乏对应的类型文件,或者在为"屎山"添加类型声明补充时,也是投机取巧
// 场景三、在定义object时,为object属性指定类型, 不想额外维护一个interface,也是投机取巧
const seriesData = {
"clusterId": [] as string[],
"clusterName": [] as string[],
"maxTime": [] as number[]
}
获取有个已知对象的类型
csharp
const optionRefType: typeof optionRef = {} as typeof optionRef;
报错:元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型...
typescript
// 使用Record指定key值类型
type Record<K extends string | number | symbol, T> = { [P in K]: T; }
// Construct a type with a set of properties K of type T
//example
const resourceUsageOptions:Record<string, string> = {
name: 'CPU',
id: '2322',
label: 'CPU机时'
}
// 或增加一个声明
interface ResourceUsageOptions {
[key: string]: any
name: string,
id: string,
label: string
}
万一后端用同一个接口返回不同的实体类型...
还是可以解决的:使用联合声明
kotlin
// 返回实例情况1
interface TopologyOfClusterUserInGroupRes {
// ...
}
// 返回实例情况2
interface TopologyOfOrgRes {
// ...
}
// 联合适配类型
type AdaptedTopologyOfClusterUserAndOrgRes = TopologyOfClusterUserInGroupRes & TopologyOfOrgRes
获取数组元素的类型
ini
const arr = [1,2,3]
type ArrItemType= typeof arr.value[number]
AI时代-使用一个趁手的工具-CURSOR
哪里有错修哪里,不会的话,一键问AI