cbd*_*per 6 overloading optional-parameters typescript typescript-typings
我的目标是根据可选condition: "CONDITION"参数的存在返回不同的类型。我正在尝试在不诉诸超载的情况下实现这一目标。
type TYPE_1 = "TYPE_1"
type TYPE_2 = "TYPE_2"
type CONDITION = "CONDITION"
function foo(condition?: CONDITION): TYPE_1 | TYPE_2 {
if (condition) {
return "TYPE_1";
}
else {
return "TYPE_2";
}
}
const shouldBeType_1 = foo("CONDITION"); // ERROR: THIS IS BEING EVALUATED AS UNION TYPE: "TYPE_1" | "TYPE_2"
const shouldBeType_2 = foo(); // ERROR: THIS IS BEING EVALUATED AS UNION TYPE: "TYPE_1" | "TYPE_2"
Run Code Online (Sandbox Code Playgroud)
通过重载可以很容易地实现这一点:
/* ########################################### */
/* #### THIS IS EASY TO DO WITH OVERLOADS #### */
/* ########################################### */
function foo_overloaded(): TYPE_2
function foo_overloaded(condition: "CONDITION"): TYPE_1
function foo_overloaded(condition?: "CONDITION"): TYPE_1 | TYPE_2 {
if (condition) {
return "TYPE_1";
}
else {
return "TYPE_2";
}
}
const overloaded_shouldBeType_1 = foo_overloaded("CONDITION"); // SUCCESS: THIS IS TYPE_1
const overloaded_shouldBeType_2 = foo_overloaded(); // SUCCESS: THIS IS TYPE_2
Run Code Online (Sandbox Code Playgroud)
在不超载的情况下执行此操作的正确方法是什么?或者我是否把它复杂化了,而超载只是在这种情况下的解决办法?
SO 上也有这个问题:TypeScript: function return type based on argument, without重载
它建议应该使用接口作为返回类型的映射,例如:
interface Registry {
A: number,
B: string,
C: boolean
}
function createType<K extends keyof Registry>(type: K, value: Registry[K]): Registry[K] {
return value;
}
Run Code Online (Sandbox Code Playgroud)
但我不能那样做,因为condition两者都是"CONDITION" | undefined。那么如何映射undefined类型呢?我也尝试使用条件类型来做到这一点。就像是:
type RETURN_TYPE<T extends undefined | "CONDITION"> = T extends "CONDITION" ? TYPE_1 : TYPE_2;
Run Code Online (Sandbox Code Playgroud)
但这也不起作用。
我想说在这种情况下你会使用重载函数,你可以通过以下方法部分解决这个问题:
function foo<T extends CONDITION | undefined>(condition?: T): T extends CONDITION ? TYPE_1 : TYPE_2 {
if (condition) {
//`as any` is intentional here: /sf/ask/3894921201/
return "TYPE_1" as any;
} else {
return "TYPE_2" as any;
}
}
Run Code Online (Sandbox Code Playgroud)
有了这个,以下工作正常:
const shouldBeType_1 = foo("CONDITION") // It is TYPE_1;
Run Code Online (Sandbox Code Playgroud)
但是当你不传递任何参数时它就不起作用:
const shouldBeType_2 = foo(); // It is TYPE_1 | TYPE_2
Run Code Online (Sandbox Code Playgroud)
当然,如果直接传递 undefined ,它就可以正常工作:
const shouldBeType_2 = foo(undefined); // It is TYPE_2;
Run Code Online (Sandbox Code Playgroud)
长话短说,现在解决您的问题的最干净的方法是使用函数重载。
编辑 正如已经指出的那样,如果我为泛型类型添加默认参数,这也适用于省略的参数。
function foo<T extends CONDITION | undefined = undefined>(condition?: T): T extends CONDITION ? TYPE_1 : TYPE_2 {
if (condition) {
return "TYPE_1" as any;
} else {
return "TYPE_2" as any;
}
}
// Both work:
const shouldBeType_1 = foo("CONDITION") // It is TYPE_1;
const shouldBeType_2 = foo(); // It is TYPE_2;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3330 次 |
| 最近记录: |