vue3 UnwrapRef 与 unref的区别
unwrapRef和unref在Vue3中有着不同的用途和功能
unwrapRef
UnwrapRef主要用于类型系统,用于解套Ref对象。在TypeScript中,UnwrapRef通过类型推断来处理嵌套的Ref对象,确保类型安全。例如,如果有一个Ref对象包裹着另一个Ref对象,UnwrapRef可以帮助解析出最底层的原始类型。UnwrapRef的定义如下:
type UnwrapRef<T> = T extends Ref<infer V> ? UnwrapRefSimple<V> : UnwrapRefSimple<T>
type UnwrapRefSimple<T> = T extends |Function |CollectionTypes |BaseTypes ? T : never
这表明UnwrapRef会处理函数、集合类型、基本类型等,但对于数组和对象,如果内部包含Ref对象,则会进行深层解套。
keyof
type Obj = {
foo: number;
bar: string;
};
type Keys = keyof Obj; // "foo" | "bar"
const obj: Obj = {
foo: 0,
bar: '',
};
obj.bar = 'h1';
obj.foo = 1;
console.log(obj);
// 定义 getProperty 函数
function getProperty<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
// 方法一:声明变量
const key: Keys = 'foo';
console.log(getProperty(obj, key));
// 方法二:定义函数
function logKey(key: Keys): void {
console.log(key);
}
logKey('bar');
// 方法三:创建数组
const keys: Keys[] = ['foo', 'bar'];
keys.forEach((key) => {
console.log(getProperty(obj, key));
});
infer
type Unpack<T> = T extends Array<infer R> ? R : T;
type NumArr = Array<number>;
type U = Unpack<NumArr>; // number
// 使用 Unpack<T> 提取数组元素类型
type StringArray = Array<string>;
type StringType = Unpack<StringArray>; // string
// 使用 NumArr 作为变量类型
const numbers: NumArr = [1, 2, 3];
// 使用 U 作为变量类型
const num: U = 42;
console.log(numbers); // 输出: [1, 2, 3]
console.log(num); // 输出: 42
说明:
infer
是 TypeScript 中条件类型的一部分,用于从类型中提取子类型。它的作用是从条件类型中的泛型参数推导出具体的类型。具体逻辑如下:
- 在条件类型
T extends U ? X : Y
中,如果T
满足U
的约束,可以通过infer
提取T
的子类型。infer
通常与extends
配合使用,用于匹配和捕获类型。在代码中:
type Unpack<T> = T extends Array<infer R> ? R : T;
- 如果
T
是数组类型,则通过infer R
提取出数组的元素类型R
。- 如果
T
不是数组类型,则直接返回T
。例如:
Unpack<number[]>
返回number
。Unpack<string[]>
返回string
。
unref
unref函数用于获取ref对象当前的原始值。在模板或计算属性中使用ref对象时,Vue会自动解包ref对象,直接使用其value属性。但是,在TypeScript类型系统中,unref提供了一种类型安全的方式来获取ref对象的值。
const count = ref(0)
const value = unref(count) // 获取count的当前值
const value = count.value // 获取count的当前值
总结
- UnwrapRef主要用于类型系统,确保类型安全地解析嵌套的Ref对象。
- unref用于在运行时获取ref对象的当前值,提供类型安全的方式访问ref的值。
可以在演练场试试看:
TypeScript: 演练场 - 一个用于 TypeScript 和 JavaScript 的在线编辑器