我正在尝试编写一个函数,该函数接受boolean类型的参数并根据输入的值返回两种类型之一。我发现了两种方法:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
if (x) {
return 3;
} else {
return "string";
}
}
TypeScript在这里说Type '3'/'"string"' is not assignable to type 'B extends true ? number : string'.
我的其他方法如下:
function dependsOnParameter(x: true): number;
function dependsOnParameter(x: false): string;
function dependsOnParameter(x: boolean): number | string {
if (x) {
return 3;
} else {
return "string";
}
}
此编译;但是,如果我尝试使用我的函数:
function calling(x: boolean) {
dependsOnParameter(x);
}
我得到Argument of type 'boolean' is not assignable to parameter of type 'false'
。
无需使用any
,有什么方法可以实现我想要的吗?
答案 0 :(得分:3)
两种方法均有效。如果您的函数在返回中使用条件类型,则将需要使用类型断言,因为typescript不会尝试推断条件类型,因为它包含一个自由类型参数:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
if (x) {
return 3 as any;
} else {
return "string"as any;
}
}
这种方法使用您要避免的any
。
我们可以使用的第二种方法是不复制类型断言,只需复制最后一个签名即可:
function dependsOnParameter(x: true): number;
function dependsOnParameter(x: false): string;
function dependsOnParameter(x: boolean): number | string
function dependsOnParameter(x: boolean): number | string {
if (x) {
return 3;
} else {
return "string";
}
}
function calling(x: boolean) {
dependsOnParameter(x); // returns number| string
dependsOnParameter(true); // returns number
dependsOnParameter(false); // returns string
}
最后一个签名是实现签名,并且不能公开访问。您可以通过复制使其可访问。编译器不够聪明,无法将两个重载与true
/ false
结合起来并确定返回类型为string|number
修改
我们还可以将两种方法结合起来以减少签名:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string
function dependsOnParameter(x: boolean): number | string{
if (x) {
return 3;
} else {
return "string";
}
}
答案 1 :(得分:1)
这是正确的方法:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
return (x === true ? 3 : "string") as B extends true ? number : string;
}
在这里,条件本身(B扩展为true?number:string)被视为一种类型。这种类型称为Conditional Type。
答案 2 :(得分:0)
您可以这样写
function dependsOnParameter<B extends boolean, C = B extends true ? number : string>(x: B): C {
if (x) {
return 3 as unknown as C;
} else {
return "string" as unknown as C;
}
}