构建在保持类型安全的同时处理多重变化的 Vue 组件可能很棘手。让我们深入研究如何使用变体 Props 模式(VPP) - 一种强大的方法,它使用 TypeScript 的可区分联合类型与 Vue 的组合式 API 来创建真正类型安全的组件变体。
Vue 中的 Variant Props 模式将 TypeScript 的可区分联合与 Vue 的 prop 系统相结合,以创建类型安全的组件变体。我们不使用复杂类型实用程序,而是将不兼容的 props 显式标记为 never,以防止在编译时混合 props:
ts 自动换行 复制
interface BaseProps {
title : string
}
type SuccessProps = BaseProps & {
variant : " success "
message : string
errorCode ? : never
}
type ErrorProps = BaseProps & {
variant : " error "
errorCode : string
message ? : never
}
type Props = SuccessProps | ErrorProps
18 行 该模式提供了编译时安全性、出色的 IDE 支持和可靠的 vue-tsc 兼容性。非常适合需要多个互斥道具组合的组件。
想象一下:您正在构建一个需要处理成功和错误状态的通知组件。每个类型都有自己特定的属性:
成功需要 message
和 duration
错误需要 errorCode
和 retryable
标志 如果没有适当的安全类型,开发人员可能会意外的混用这些 props
html 自动换行 复制
<!-- 🚨 Mixing success and error props -->
< NotificationAlert
variant = " primary "
title = " Data Saved "
message = " Success! "
errorCode = " UPLOAD_001 "
:duration = " 5000 "
@close = " handleClose "
/>
您的第一直觉可能是定义单独的接口:
ts 自动换行 复制
interface SuccessProps {
title : string
variant : " primary " | " secondary "
message : string
duration : number
}
interface ErrorProps {
title : string
variant : " danger " | " warning "
errorCode : string
retryable : boolean
}
// 🚨 This allows mixing both types!
type Props = SuccessProps & ErrorProps
17 行 有什么问题?这种方法允许开发人员同时使用 success 和 error props - 绝对不是我们想要的!
TypeScript 提示: never 类型是 TypeScript 中的一种特殊类型,表示从未出现的值。当属性被标记为 never 时,TypeScript 确保永远不能将值分配给该属性。这使得它非常适合创建互斥的 props,因为它可以防止开发人员意外地使用不应该同时存在的 props。
never 类型通常出现在 TypeScript 中的几种场景中:
永不返回的函数(抛出错误或具有无限循环) switch 语句中的详尽类型检查 不可能的类型交叉(例如 string & number) 使属性互斥,就像我们在这种模式中所做的那样 使其与当前的 defineProps 实现兼容的主要技巧是使用 never 来显式标记未使用的变体道具。
ts 自动换行 复制
// Base props shared between variants
interface BaseProps {
title : string
}
// Success variant
type SuccessProps = BaseProps & {
variant : " primary " | " secondary "
message : string
duration : number
// Explicitly mark error props as never
errorCode ? : never
retryable ? : never
}
// Error variant
type ErrorProps = BaseProps & {
variant : " danger " | " warning "
errorCode : string
retryable : boolean
// Explicitly mark success props as never
message ? : never
duration ? : never
}
// Final props type - only one variant allowed!
type Props = SuccessProps | ErrorProps
28 行 这是使用 Variant Props 模式的完整通知组件:
vue playground preview
Variant Props Pattern (VPP) 提供了一种构建类型安全的 Vue 组件的强大方法。虽然 Vue 团队正在努力改进 vuejs/core#8952 中对受歧视联合体的本机支持,但这种模式今天提供了一个实用的解决方案:
不幸的是,目前不起作用的是使用像 Xor 这样的辅助实用程序类型,这样我们就不必手动将未使用的变体属性标记为从不。当你这样做时,你会从 vue-tsc 收到错误。
Xor 等辅助类型的示例:
ts 自动换行 复制
type Without < T , U > = { [ P in Exclude < keyof T , keyof U >] ? : never }
type XOR < T , U > = T | U extends object ? ( Without < T , U > & U ) | ( Without < U , T > & T ) : T | U
// Success notification properties
interface SuccessProps {
title : string
variant : " primary " | " secondary "
message : string
duration : number
}
// Error notification properties
interface ErrorProps {
title : string
variant : " danger " | " warning "
errorCode : string
retryable : boolean
}
// Final props type - only one variant allowed! ✨
type Props = XOR < SuccessProps , ErrorProps >
22 行
评论区
评论加载中...