Typescript 函数返回类型基于可选参数存在而不使用函数重载 [英] Typescript function return type based on optional parameter presence without using function overloads
问题描述
我的目标是根据可选的 condition: CONDITION"
参数的存在返回不同的类型.我正在努力在不诉诸重载的情况下实现这一目标.
My goal here is to return a different type based on the presence of a optional condition: "CONDITION"
parameter. And I'm trying to accomplish this without resorting to overloads.
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"
这很容易通过重载来实现:
This is easy to accomplish with overloads:
/* ########################################### */
/* #### 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
没有重载的正确方法是什么?还是我把它复杂化了,重载只是在这种情况下的方法?
What is the proper way of doing it without overloads? Or am I over complicating it and overloading is simply the way to go in this situation?
SO 上也有这个问题:TypeScript:基于参数的函数返回类型,无需重载
Also there is this question here on SO: TypeScript: function return type based on argument, without overloading
它建议应该使用接口作为返回类型的映射,例如:
It suggests that an interface should be used as a map to the return type, like:
interface Registry {
A: number,
B: string,
C: boolean
}
function createType<K extends keyof Registry>(type: K, value: Registry[K]): Registry[K] {
return value;
}
但我不能那样做,因为 condition
要么是 "CONDITION"|未定义
.那么如何映射 undefined
类型呢?我也试过用条件类型来做.类似的东西:
But I can't do that, because condition
is either "CONDITION" | undefined
. So how can I map the undefined
type? I also tried doing that with conditional type. Something like:
type RETURN_TYPE<T extends undefined | "CONDITION"> = T extends "CONDITION" ? TYPE_1 : TYPE_2;
但这也没有用.
推荐答案
我会说在这种情况下你会使用重载函数,你可以通过以下方式部分解决这个问题:
I would say you would go with overloaded functions in this case, you can solve this partly with the following:
function foo<T extends CONDITION | undefined>(condition?: T): T extends CONDITION ? TYPE_1 : TYPE_2 {
if (condition) {
//`as any` is intentional here: https://stackoverflow.com/questions/55641731/typescript-conditional-type-complains-type-not-assignable
return "TYPE_1" as any;
} else {
return "TYPE_2" as any;
}
}
有了这个,以下工作正常:
With this, the following works fine:
const shouldBeType_1 = foo("CONDITION") // It is TYPE_1;
但是当您不传递任何参数时,它将不起作用:
But when you don't pass any params it would not work:
const shouldBeType_2 = foo(); // It is TYPE_1 | TYPE_2
当然,如果你直接传递 undefined,它就可以正常工作:
Of course if you pass undefined directly, it works correctly:
const shouldBeType_2 = foo(undefined); // It is TYPE_2;
长话短说,现在,解决您的问题最干净的方法是使用函数重载.
So long stroy short, right now, the cleanest approach for your problem, is to use function overloading.
编辑正如已经指出的那样,如果我为泛型类型添加默认参数,这也适用于省略的参数.
EDIT As it has been pointed out if I add a default parameter for the generic type, this would work with omitted param as well.
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;
这篇关于Typescript 函数返回类型基于可选参数存在而不使用函数重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!