TypeScript 当其中一个返回类型是条件类型时,函数的推断返回类型不正确,

gopyfrb3  于 5个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(55)

Bug报告

🔎 搜索词

忽略返回类型泛型条件

🕗 版本与回归信息

  • 在所有我尝试的版本中,都存在这种行为,我也查看了关于 return 的常见问题解答条目。

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

type Foo<T> = {
    template: T;
}

type Bar<T> = T extends boolean ? Foo<number> : Foo<string>;

type Baz<T extends boolean> = Bar<T> extends infer InferredFoo
    ? InferredFoo extends Foo<any>
        ? "yes"
        : never
    : never;

function test<T extends boolean>(opts: T) {
    const x = false;

    // If you comment the line below, this function starts
    // returning Baz<T> as expected, which in turn makes `result`
    // have the type "yes".
    // The if statement below should have no impact to the
    // return type of the function, other than adding `| null`.
    // After all, you can force the return type of the function
    // to be `Baz<T> | null` and it still works fine.
    if (x) return null;

    return {} as Baz<T>;
}

const result = test(true);

🙁 实际行为

result 的类型为 null

🙂 预期行为

result 应该具有 null | "yes" 的类型

jmp7cifd

jmp7cifd1#

Bar<T> extends infer InferredFoo 的意图是什么?
无论如何,这非常奇怪。已移除的可能的误导信息:

type Foo<T> = {
    template: T;
}

type Bar<T> = T extends string ? Foo<number> : Foo<string>;

type Baz<T extends string> = Bar<T> extends infer InferredFoo
    ? InferredFoo extends Foo<unknown>
        ? "yes"
        : never
    : never;

function test<T extends string>(opts: T) {
    if (Math.random() > 0.5) {
        return null;
    }
    return {} as Baz<T>;
}

// null
const result = test("");

type Foo<T> = {
    template: T;
}

type Bar<T> = T extends string ? Foo<number> : Foo<string>;

type Baz<T extends string> = Bar<T> extends infer InferredFoo
    ? InferredFoo extends Foo<unknown>
        ? "yes"
        : "no_1" // <- never to no_1
    : "no_2"; // <- never to no_2

function test<T extends string>(opts: T) {
    if (Math.random() > 0.5) {
        return null;
    }
    return {} as Baz<T>;
}

// result: null | "yes"
const result = test("");
3phpmpom

3phpmpom2#

编写 Bar<T> extends infer InferredFoo 的目的是什么?
这是我为了将一个较长的变量和模板变得更短,以便我可以多次重用它而不必每次都完整地输入它。不过我现在明白这实际上并不必要,因为我在实际代码中只使用 InferredFoo 一次。

相关问题