You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中Readonly<T> & T的含义及Vue3源码使用疑问

Vue 3 源码中 Readonly<T> & T 写法的原因

先看这段Vue 3的类型工具代码:

export type StrictUnwrapSlotsType<
  S extends SlotsType,
  T = NonNullable<S[typeof SlotSymbol]>,
> = [keyof S] extends [never] ? Slots : Readonly<T> & T

你提到的示例存在一个误区——Readonly<User> & User和User的类型并非完全一致。实际在TypeScript中,前者会将所有属性标记为只读:

interface User {
  name: string,
  age: number
}

type intersectionUser = Readonly<User> & User

const user: intersectionUser = { name: "Alice", age: 25 }
user.name = "Bob" // ❌ TypeScript报错:无法分配到 "name" ,因为它是只读属性

而直接使用User类型时,属性可以正常修改。

回到Vue的场景,StrictUnwrapSlotsType是处理插槽类型的工具,Vue的设计逻辑里,插槽对象是只读的——组件不应该修改传入的插槽内容。这里用Readonly<T> & T而非直接T,主要有这些原因:

  • 强制只读约束:通过交集写法,把T的所有属性(包括嵌套属性、索引签名)都标记为只读,确保使用该类型的代码无法修改插槽内容,契合Vue的设计意图。
  • 结构类型兼容:TypeScript的结构类型系统允许把普通T类型的值赋值给Readonly<T> & T(结构兼容),但反过来不行,形成了单向的类型安全屏障。
  • 覆盖复杂类型场景:当T包含索引签名、可选属性时,Readonly<T> & T能确保所有层级的属性都被设为只读,而直接T做不到这一点。比如带有索引签名的插槽类型:
    type SlotObj = { [key: string]: () => VNode }
    type StrictSlot = Readonly<SlotObj> & SlotObj
    
    const slots: StrictSlot = { default: () => h('div') }
    slots.default = () => h('p') // ❌ 报错:索引签名仅允许读取
    

这种写法既保留了T的原始结构,又通过类型交集强化了不可变性,是Vue在类型层面保障插槽安全的设计手段。

内容的提问来源于stack exchange,提问作者fiveyi li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:08:11