typescript 条件类型的简单函数

gkn4icbw  于 2023-01-27  发布在  TypeScript
关注(0)|答案(3)|浏览(118)

下面的函数基本上是从关于使用 conditional types 的typescript手册中提取出来的,但是它并不起作用:

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

typescript 报告:

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'.

我想我忽略了一些明显的东西,我怎样构造这个函数,使typescript根据函数的参数正确地推断类型呢?
我意识到这个特定的问题可以使用函数签名重载来解决,但是我想学习更多关于条件类型的知识。

3gtaxfhh

3gtaxfhh1#

简而言之,你不能。没有值可以赋给一个未解析的条件类型(一个仍然依赖于自由泛型类型变量的条件类型)。你唯一能做的就是使用类型Assert。

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

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

function test<T extends boolean>(a: T): T extends true ? string : number
function test(a: boolean): number | string {
    return (a ? '1' : 1)
}
czq61nw1

czq61nw12#

TypeScript可以正确地推断返回类型。但它没有检查运行时逻辑是否遵循条件类型中指定的条件,在您的情况下,它会导致编译时错误。您可以使用索引类型访问来根据条件获取所需的类型,从而避免此错误。
与你问题中声明的test相比,它有不同的行为,也就是说,如果在编译时类型未知,它会推断联合类型。仍然不会检查实现是否符合条件类型逻辑,但不会有错误,也不需要类型Assert:

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
cyvaqqii

cyvaqqii3#

function关键字对我不起作用,但在arrow函数定义中起作用

type counterType<T = boolean> = (obj:T) => T extends true? 
 string:number;

 let counter: counterType = (obj) =>{
   if(obj)
    return "abc";
    return 123
}

console.log(counter(true)) //returns ABC (string)

相关问题