带条件类型的简单函数

Joh*_*ohn 5 typescript conditional-types

以下功能主要是从使用条件类型打字稿手册部分中提取的,但它不起作用:

function test<T extends boolean>(a: T): T extends true ? string : number {
  return a ? '1' : 1
}
Run Code Online (Sandbox Code Playgroud)

打字稿报告说:

Type '1 | "1"' is not assignable to type 'T extends true ? string : number'.
  Type '1' is not assignable to type 'T extends true ? string : number'.
Run Code Online (Sandbox Code Playgroud)

我想我错过了一些明显的东西。我怎样才能构造这个函数,以便打字稿根据函数的参数正确推断类型?

我意识到可以使用函数签名重载来解决这个特定问题,但我想了解更多关于条件类型的信息。

Tit*_*mir 7

简短的回答是你不能。无法为未解析的条件类型(仍然依赖于自由泛型类型变量的条件类型)分配任何值。您唯一能做的就是使用类型断言。

function test<T extends boolean>(a: T): T extends true ? string : number {
  return (a ? '1' : 1)  as any
}
Run Code Online (Sandbox Code Playgroud)

条件类型对于表达参数之间的关系很有用,但在实现函数时却无济于事。另一种方法是使用更宽松的实现签名。

function test<T extends boolean>(a: T): T extends true ? string : number
function test(a: boolean): number | string {
    return (a ? '1' : 1)
}
Run Code Online (Sandbox Code Playgroud)


art*_*tem 5

TypeScript 确实可以正确推断返回类型。它不做的是,它不检查运行时逻辑是否遵循条件类型中指定的条件,在您的情况下,它会导致编译时错误。您可以通过使用索引类型访问来根据条件获取所需的类型来避免该错误。

与您的问题中声明的行为相比,它将具有不同的行为test,即,如果编译时类型未知,它将推断联合类型。仍然不会检查实现是否符合条件类型逻辑,但不会出现错误,也不需要类型断言:

interface Selector {
    t: string;
    f: number;
}

function test<T extends boolean>(a: T): Selector[T extends true ? 't' : 'f'] {
  // NOTE: not checked that is returns correct type actually
  return a ? '1' : 1
}


const t1 = test(true);  // string
const t2 = test(false); // number
declare var b: boolean;
const t3 = test(b); // string | number, which may or may not be what you want
Run Code Online (Sandbox Code Playgroud)