[英]Why does conditional type inference in Typescript cause the type in my unref implementation to be classified as unknown?
I have implemented 2 versions of the Vuejs function "unref".我已经实现了 2 个版本的 Vuejs function“unref”。
This has one parameter which can be of type Ref<T>:{ value: T }
or anything else.它有一个参数,可以是
Ref<T>:{ value: T }
或任何其他类型。
If the parameter gets a Ref unref or unref2 returns the Ref.value otherwise it simply returns the parameter.如果参数获得 Ref unref 或 unref2 返回 Ref.value 否则它只返回参数。
The only difference between the functions is how I use the Typescript syntax.这些函数之间的唯一区别是我如何使用 Typescript 语法。
Why does Typescript has an issue with the unref2 function?为什么 Typescript 与 unref2 function 有问题?
type Ref<Value> = { value: Value };
// Returns the type of Ref<TypeOfRef> if its a Ref else return T
type GetTypeOfMaybeRef<T> = T extends Ref<infer V> ? V : T;
// works
function unref<T>(maybeRef: Ref<GetTypeOfMaybeRef<T>>|GetTypeOfMaybeRef<T>): GetTypeOfMaybeRef<T> {
if (maybeRef != null && typeof maybeRef === 'object' && "value" in maybeRef) {
return maybeRef.value;
} else {
return maybeRef;
}
}
// does not work, why?
// should be like unref.
// I know, T is just T.
// I did it to give ts a hint that T can be a Ref.
function unref2<T>(maybeRef: T extends Ref<infer Value> ? Ref<Value> : T): GetTypeOfMaybeRef<T> {
if (maybeRef != null && typeof maybeRef === 'object' && "value" in maybeRef) {
return maybeRef.value;
} else {
// why ts error?
// should it not be the same as unref?
return maybeRef;
}
}
const ref: Ref<number> = { value: 3 };
const numRef: Ref<number> = { value: 3 };
const num = unref(numRef)
const strRef: Ref<string> = { value: "blalba" };
const text = unref(strRef)
Deriving a generic type from an argument that has a conditional type is going to hit and miss.从具有条件类型的参数派生泛型类型会很失败。 Sometimes Typescript can figure out simple cases, but when it gets complicated things will start to fail.
有时 Typescript 可以解决简单的问题,但当它变得复杂时,事情就会开始失败。
It's best to avoid that situation altogether.最好完全避免这种情况。
That said, You are trying very hard here, and this can be much simpler:也就是说,你在这里非常努力,这可以简单得多:
type Ref<Value> = { value: Value };
function unref<T>(maybeRef: Ref<T> | T): T {
if (maybeRef != null && typeof maybeRef === 'object' && "value" in maybeRef) {
return maybeRef.value;
} else {
return maybeRef;
}
}
There is no infer
or even any conditional types required.不需要
infer
,甚至不需要任何条件类型。 unref
takes either a Ref<T> | T
unref
采用Ref<T> | T
Ref<T> | T
and T
is returned. Ref<T> | T
和T
被返回。 Easy peasy.十分简单。
And if you need GetTypeOfMaybeRef<T>
still then you can do that without infer
:如果你仍然需要
GetTypeOfMaybeRef<T>
那么你可以在没有infer
的情况下做到这一点:
type GetTypeOfMaybeRef<T> = T extends Ref<unknown> ? T['value'] : T;
type A = GetTypeOfMaybeRef<{ value: number }> // number
type B = GetTypeOfMaybeRef<string> // string
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.