简体   繁体   English

为什么 Typescript 中的条件类型推断会导致我的 unref 实现中的类型被归类为未知?

[英]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 有问题?

Playground link 游乐场链接

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> | TT被返回。 Easy peasy.十分简单。

See playground 看游乐场


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

See Playground 看游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM