VueTypes 是专门为 Vue 组件提供类型校验的工具库(兼容 Vue2/Vue3),在 Vue3 + TypeScript 项目中,它能补充 TS 类型系统的不足 —— 尤其适合「非 TS 项目的类型校验」「复杂 props 约束」「运行时类型验证」场景,是 CRM 这类复杂业务系统的类型安全 “补充方案”。

使用的意义不太大, 核心原因是:Vue3 + TS 原生能力已经覆盖了 VueTypes 的 90% 核心诉求,且更贴合 Vue3 的设计理念:

一、核心定位(为什么用 VueTypes?)

Vue3 本身支持 TS 类型注解,但 VueTypes 有不可替代的优势:

表格

场景

TypeScript 原生

VueTypes

静态类型检查

✅ 编译时校验

✅ 运行时校验(浏览器控制台提示)

复杂类型约束

需手写复杂类型 / 守卫

内置 shape

/arrayOf

/oneOf

等快捷方法

非 TS 项目

❌ 无法使用

✅ 纯 JS 项目也能做类型校验

默认值 + 类型联动

需手动对齐类型和默认值

内置 def()

方法,一键绑定

自定义校验规则

需写类型守卫函数

内置 custom()

方法,简化逻辑

CRM 适配场景

  • 团队混合开发(部分开发者用 JS),需统一 props 校验;
  • 复杂 props(如客户信息对象、订单列表),需精细约束字段;
  • 运行时校验(如后端返回数据异常时,前端快速定位 props 错误)。

二、快速集成(Vue3 + Vite 项目)

1. 安装依赖

bash

运行

# 核心依赖
npm install vue-types -S
# TS 类型(库自带,无需额外安装)

2. 基础用法(Vue3 组件 props 校验)

VueTypes 兼容 Vue3 的 defineProps,可直接替代原生 PropType,简化复杂类型定义:

vue

<template>
  <div class="customer-card">
    <h3>{{ customer.name }}</h3>
    <p>电话:{{ customer.phone }}</p>
    <p>状态:{{ customer.status }}</p>
  </div>
</template>

<script setup lang="ts">
import VueTypes from 'vue-types';

// 方式1:纯 VueTypes 校验(兼容 JS/TS)
const props = defineProps({
  // 基础类型 + 默认值
  title: VueTypes.string.def('客户信息'),
  // 复杂对象 + 字段约束
  customer: VueTypes.shape({
    id: VueTypes.string.required(), // 必填字符串
    name: VueTypes.string.required(),
    phone: VueTypes.string.pattern(/^1[3-9]\d{9}$/), // 手机号正则校验
    status: VueTypes.oneOf(['active', 'inactive', 'pending']).def('active'), // 枚举值
    followTime: VueTypes.date, // 日期类型
    tags: VueTypes.arrayOf(VueTypes.string).def([]) // 字符串数组
  }).required(),
  // 自定义校验
  orderAmount: VueTypes.custom((val) => {
    return typeof val === 'number' && val >= 0;
  }).def(0),
  // 函数类型
  onFollow: VueTypes.func.def(() => {})
});

// 方式2:TS + VueTypes 结合(推荐,兼顾静态+运行时校验)
interface Customer {
  id: string;
  name: string;
  phone: string;
  status: 'active' | 'inactive' | 'pending';
}

const propsWithTS = defineProps({
  customer: VueTypes.shape<Customer>({
    id: VueTypes.string.required(),
    name: VueTypes.string.required(),
    phone: VueTypes.string.pattern(/^1[3-9]\d{9}$/),
    status: VueTypes.oneOf(['active', 'inactive', 'pending']).def('active')
  }).required()
});
</script>

三、核心 API 详解(CRM 高频使用)

1. 基础类型(与 Vue 原生 props 对齐)

表格

VueTypes API

说明

示例

VueTypes.string

字符串类型

VueTypes.string.def('默认值')

VueTypes.number

数字类型

VueTypes.number.required()

VueTypes.boolean

布尔类型

VueTypes.boolean.def(false)

VueTypes.array

数组类型

VueTypes.array.def([])

VueTypes.object

对象类型

VueTypes.object.def({})

VueTypes.func

函数类型

VueTypes.func.def(() => {})

VueTypes.date

日期类型

VueTypes.date

2. 复杂类型(CRM 核心)

(1)shape:对象结构约束

用于约束客户信息、订单信息等复杂对象(CRM 最常用):

typescript

运行

// 约束订单对象
const props = defineProps({
  order: VueTypes.shape({
    id: VueTypes.string.required(),
    amount: VueTypes.number.min(0).required(), // 最小值约束
    createTime: VueTypes.date.required(),
    items: VueTypes.arrayOf(
      VueTypes.shape({
        productId: VueTypes.string,
        quantity: VueTypes.number.min(1)
      })
    ).def([])
  }).required()
});
(2)arrayOf:数组元素约束

用于约束订单列表、客户标签列表等:

typescript

运行

// 客户标签列表(仅允许字符串)
VueTypes.arrayOf(VueTypes.string).def([])
// 订单列表(仅允许订单对象)
VueTypes.arrayOf(VueTypes.shape({ id: VueTypes.string, amount: VueTypes.number }))
(3)oneOf:枚举值约束

用于状态类字段(如订单状态、客户状态):

typescript

运行

// 订单状态枚举
VueTypes.oneOf(['pending', 'paid', 'shipped', 'completed']).def('pending')
(4)oneOfType:多类型约束

用于支持多种类型的字段(如 ID 可传字符串 / 数字):

typescript

运行

// 客户ID:字符串或数字
VueTypes.oneOfType([VueTypes.string, VueTypes.number]).required()

3. 修饰符(精细化约束)

表格

修饰符

说明

示例

.required()

必填项

VueTypes.string.required()

.def(value)

设置默认值

VueTypes.string.def('默认')

.min(n)

数字最小值

VueTypes.number.min(0)

.max(n)

数字最大值

VueTypes.number.max(100)

.len(n)

字符串 / 数组长度

VueTypes.string.len(11)

.pattern(re)

字符串正则校验

VueTypes.string.pattern(/^\d+$/)

.instanceOf()

类实例校验

VueTypes.instanceOf(Date)

4. 自定义校验(custom

用于复杂业务规则校验(如 CRM 中 “折扣率必须 0-1 之间”):

typescript

运行

const props = defineProps({
  // 折扣率:0-1 之间的数字
  discount: VueTypes.custom((val) => {
    return typeof val === 'number' && val >= 0 && val <= 1;
  }).def(1),
  // 自定义错误提示
  customerCode: VueTypes.custom((val) => {
    const isValid = /^CRM-\d{6}$/.test(val);
    if (!isValid) {
      throw new Error('客户编码格式错误,需为 CRM-xxxxxx');
    }
    return isValid;
  }).required()
});

四、Vue3 + TS 最佳实践(CRM 开发)

1. 场景 1:封装通用类型(全局复用)

CRM 中客户、订单等类型会跨组件使用,可封装全局 VueTypes 类型:

typescript

运行

// src/types/vue-types.ts
import VueTypes from 'vue-types';

// 客户信息类型
export const CustomerType = VueTypes.shape({
  id: VueTypes.string.required(),
  name: VueTypes.string.required(),
  phone: VueTypes.string.pattern(/^1[3-9]\d{9}$/).required(),
  status: VueTypes.oneOf(['active', 'inactive', 'pending']).def('active'),
  followTime: VueTypes.date
});

// 订单信息类型
export const OrderType = VueTypes.shape({
  id: VueTypes.string.required(),
  customerId: VueTypes.string.required(),
  amount: VueTypes.number.min(0).required(),
  status: VueTypes.oneOf(['pending', 'paid', 'completed']).def('pending')
});

组件中复用:

vue

<script setup lang="ts">
import { CustomerType } from '@/types/vue-types';

const props = defineProps({
  customer: CustomerType.required(),
  orderList: VueTypes.arrayOf(OrderType).def([])
});
</script>

2. 场景 2:运行时错误捕获

VueTypes 校验失败会在控制台抛出警告,可自定义错误处理(CRM 生产环境):

typescript

运行

// src/main.ts
import VueTypes from 'vue-types';

// 自定义校验失败处理
VueTypes.config.warn = (msg) => {
  // 开发环境:控制台警告
  if (import.meta.env.DEV) {
    console.error('[VueTypes Error]', msg);
  }
  // 生产环境:上报错误监控平台
  if (import.meta.env.PROD) {
    // errorMonitor.report({ type: 'props', message: msg });
  }
};

3. 场景 3:替代 PropType(简化 TS 写法)

Vue3 原生 TS 需用 PropType 定义复杂类型,VueTypes 可简化:

typescript

运行

// 原生 TS 写法
import { PropType } from 'vue';
interface Customer { id: string; name: string; }
const props = defineProps({
  customer: {
    type: Object as PropType<Customer>,
    required: true
  }
});

// VueTypes 写法(更简洁)
const props = defineProps({
  customer: VueTypes.shape<Customer>({
    id: VueTypes.string.required(),
    name: VueTypes.string.required()
  }).required()
});

五、核心避坑点

1. TS 类型与 VueTypes 不一致

  • 问题:TS 定义 status: 'active' | 'inactive',但 VueTypes 写 oneOf(['active', 'invalid']),导致运行时校验失败;
  • 解决方案:保持 TS 类型和 VueTypes 校验规则一致,优先用 VueTypes.shape<T>() 关联 TS 接口。

2. 默认值类型不匹配

  • 问题:VueTypes.number.def('123')(默认值是字符串,类型是数字);
  • 解决方案:.def() 的值必须与前面的类型匹配,如 VueTypes.number.def(123)

3. 数组 / 对象默认值引用问题

  • 问题:VueTypes.array.def([]) 看似没问题,但复杂对象默认值需用函数返回(避免多实例共享引用);
  • 解决方案:typescript运行
// 错误:多组件实例共享同一个数组
VueTypes.array.def([])
// 正确:函数返回新数组
VueTypes.array.def(() => [])

// 对象同理
VueTypes.object.def(() => ({ name: '默认' }))

4. 忽略运行时校验

  • 问题:开发时关闭了 Vue 的 props 校验(app.config.warnHandler = () => {}),导致 VueTypes 失效;
  • 解决方案:开发环境保留 props 校验,仅在生产环境按需关闭。

六、总结(CRM 开发最佳实践)

  1. 使用场景
    • 纯 JS 项目:用 VueTypes 做运行时 props 校验;
    • TS 项目:用 VueTypes 补充运行时校验(TS 仅编译时),尤其复杂对象 / 自定义规则;
    • 团队协作:统一 props 校验规范,降低沟通成本。
  1. 最佳写法
    • 简单 props:用 TS 原生注解(如 defineProps<{ title: string }>());
    • 复杂 props:用 VueTypes.shape<T>() 结合 TS 接口,兼顾静态 + 运行时校验;
    • 全局复用:封装通用类型(如 CustomerType/OrderType),避免重复定义。
  1. 避坑核心
    • 保持 TS 类型和 VueTypes 规则一致;
    • 数组 / 对象默认值用函数返回;
    • 开发环境保留校验,生产环境自定义错误处理。

VueTypes 不是 TS 的 “替代品”,而是 “补充品”—— 在 CRM 这类复杂业务系统中,它能让 props 校验更严谨,既利用 TS 的静态类型检查,又通过运行时校验捕获生产环境的异常,提升代码健壮性。

更多推荐