Typescript 函数输出无法分配给条件类型

标签 typescript conditional-types function-signature

我有一个更复杂问题的简化版本。以下情况会导致 TSC 抛出错误:

type Demo<isTrue> = isTrue extends true ? { a: string } : isTrue extends false ? { b: string } : never;

const func = <T extends boolean>(arg: T): Demo<T> => {
    if (arg) {
        return {a: "hello" };
    } else {
        return { b: "world" };
    }
};

const out = func(true);

抛出以下错误:

    Type '{ a: string; }' is not assignable to type 'Demo<T>'.
    Type '{ b: string; }' is not assignable to type 'Demo<T>'.

底部的 out 经检查具有正确的类型,因此只有函数定义存在问题。我怎样才能更好地理解这个问题以及如何解决它?

Playground link

最佳答案

How can I understand this better?

看看this GitHub thread (另请参阅 original issue )。归根结底,TypeScript 在使用条件类型时不支持缩小函数返回类型。自Demo决议以来类型取决于泛型类型参数 T ,这和直接在返回类型注解中写条件是一样的。

如果我们重写Demo,问题应该会变得更清楚。类型(仅用于演示目的):

type D<T extends boolean> = {
    true: {
        a: string
    },
    false: {
        b: string
    }
}[`${T}`];

const func = <T extends boolean>(arg: T): D<T> => {
    if (arg) {
        return {a: "hello" }; //Type '{ a: string; }' is not assignable to type '{ a: string; } & { b: string; }'
    } else {
        return { b: "world" }; //Type '{ b: string; }' is not assignable to type '{ a: string; } & { b: string; }'
    }
};

现在应该很清楚 D<T>直到您为类型形参提供实参为止,该问题仍然无法解决。这就是为什么const out = func(true);推断正确。

How do I solve it?

您几乎只能使用类型断言,如 as Demo<T>或者删除泛型类型参数并使用重载重写签名,如 captain-yossarian's 中所述。回答。

关于Typescript 函数输出无法分配给条件类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66310189/

相关文章:

angularjs - Release模式下没有源映射文件

typescript - 编写一个在泛型上使用查找类型的函数

typescript - 从类的属性和方法中提取特定类型并将其添加到接口(interface)

typescript - 联合类型和条件类型的问题

haskell - 将 IO (Maybe (IO (Maybe a))) 减少到 IO (Maybe a)

c++ - 是否可以从(Functor 成员的)函数签名中检索参数类型以用于模板?

javascript - TypeScript - 通用函数的 ReturnType 不起作用

typescript - 使用 Typescript 导入 Electron 类

node.js - 在微服务之间共享 Prisma 类型

php - 传递默认值而不是引用