TypeScript: 条件类型和使用布尔参数控制返回类型

13

如何使用条件类型而不是重载签名来重写此内容?

function foo(returnString: true): string;
function foo(returnString: false): number;
function foo(returnString: boolean) {
  return returnString ? String(Math.random()) : Math.random();
}

我尝试了以下代码,但是没有 as any,它不能被编译:

function foo<T extends boolean>(returnString: T): T extends true ? string : number {
  return (returnString ? String(Math.random()) : Math.random()) as any;
}

我该如何摆脱“as any”?
这个错误信息真的没什么用:
Type 'string | number' is not assignable to type 'T extends true ? string : number'.
  Type 'string' is not assignable to type 'T extends true ? string : number'.

2
看起来这是一个已知问题,他们在那个问题中提到any转换或重载是当前的解决方法。此外,在他们的六月设计会议记录中,他们提到:今天,除非它是另一个条件类型,否则类型不能分配给条件类型。,所以他们意识到了这一点,未来可能会有修复。 - CRice
@CRice 谢谢!在问问题之前,我花了很多时间尝试找到相应的问题,但它藏得太好了。 - thorn0
3个回答

7

我不太确定编译器为什么不能直接接受这个代码(对TypeScript不是非常熟悉),但你可以尝试以下方法:

function foo<T extends boolean>(returnString: T): T extends true ? string : number;
function foo<T extends boolean>(returnString: T): string | number {
  return returnString ? String(Math.random()) : Math.random();
}

基本上,您需要将声明(公共签名)和实现分开,将更准确的签名赋予声明,将更广泛的签名赋予实现。


1
这个代码是可以运行的,但我认为条件类型应该让我们在这种情况下完全摆脱声明签名。 - thorn0
1
我的真实签名当然比这个例子更复杂。保留两份副本感觉不对。 - thorn0

0

我也遇到了这个问题,事实上我并没有解决它。 但是我找到了一种避免使用"any"类型的方法,通过将条件返回类型分配给一个泛型。然后可以使用该泛型来替代"any"。

function foo<T extends boolean, Z = T extends true ? string : number >(returnString?: T ): Z  {
    if(returnString) {
        return String(Math.random()) as Z ;
    }
    return Math.random() as Z ;
}

0

我认为你应该这样编写你的函数:

export class MyService {

    request(param: false): string; // must a defination;

    request(param: true): number;

    request(param: any): string | number {
        return null;
    }

}

借鉴自 https://github.com/angular/angular/blob/master/packages/common/http/src/client.ts

使用 typescript 2.8,您可以编写如下的函数:

function fun<T extends true | false>(t: T): T extends true ? string : number {
    return null;
}

你尝试编译过这段代码吗?看起来好像无法工作。如果尝试成功,请添加编译示例。 - Cerberus
1
我明白了。这正是原帖中明确表示不希望出现的情况。 - Cerberus
抱歉,这是我的错。这是Typescript 2.8的一个特性,你可以像这样编写代码:function fun(t: T): T extends true ? string : number { return null; } - zhimin
1
我已经在你的函数中添加了返回语句(就像问题中一样)- 它似乎无法区分 truefalseT extends boolean 独立于值。 - Cerberus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接