Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 依赖于函数参数属性的函数返回类型_Typescript - Fatal编程技术网

Typescript 依赖于函数参数属性的函数返回类型

Typescript 依赖于函数参数属性的函数返回类型,typescript,Typescript,我正在为TypeScript中的API创建一个包装器 一个API调用可以返回两种类型的响应:基本响应和扩展响应,具体取决于参数属性 如果参数属性为true,则响应将被扩展。如果参数属性未提供或为false,则响应将是基本的 以下是代码示例: 接口参数{ 令牌:字符串; 区域:字符串; extendedResponse?:布尔值; } 界面碱基应答{ ID:字符串; } 接口扩展响应扩展基本响应{ 扩展响应属性:对象; } 函数返回响应(args:args):基本响应|扩展响应{ if(参数ext

我正在为TypeScript中的API创建一个包装器

一个API调用可以返回两种类型的响应:基本响应和扩展响应,具体取决于参数属性

如果参数属性为true,则响应将被扩展。如果参数属性未提供或为false,则响应将是基本的

以下是代码示例:

接口参数{
令牌:字符串;
区域:字符串;
extendedResponse?:布尔值;
}
界面碱基应答{
ID:字符串;
}
接口扩展响应扩展基本响应{
扩展响应属性:对象;
}
函数返回响应(args:args):基本响应|扩展响应{
if(参数extendedResponse){
返回{ID:“foobar”,扩展响应属性:{};
}
返回{ID:“foobar”}
}
让res1=returnResponse({令牌:“asdf”,区域:“us”,extendedResponse:true});
游乐场:

但是,此代码不向此方法的使用者显示已返回
扩展响应
,它将类型显示为
基本响应|扩展响应
,并且不显示intellisense中的
扩展响应属性

我最接近解决这个问题的方法是使用以下代码:

接口参数{
令牌:字符串;
区域:字符串;
}
接口扩展参数扩展参数{
扩展响应:正确;
}
界面碱基应答{
ID:字符串;
}
接口扩展响应扩展基本响应{
扩展响应属性:对象;
}
函数返回响应(args:args):基本响应;
函数returnResponse(args:ExtendedArgs):ExtendedResponse;
函数返回响应(args:args | ExtendedArgs):基本响应| ExtendedResponse{
if(args作为扩展args){
返回{ID:“foobar”,扩展响应属性:{};
}
返回{ID:“foobar”}
}
让res1=returnResponse({令牌:“asdf”,区域:“us”});
让res2=returnResponse({令牌:“asdf”,区域:“asdf”,extendedResponse:true});
连结至游乐场:

但是我并不喜欢这个解决方案,因为这个方法的使用者需要处理函数重载和两种类型的输入参数。

只有一个输入参数,恰好它可以有
extendedResponse:boolean
属性。两个输入参数使其不那么直观

是否有一种基于类型脚本的方法可以解决这个问题?


更新

更好的解决方案是为输入参数使用联合类型:

接口参数{
令牌?:字符串;
区域?:字符串;
}
界面碱基应答{
ID:字符串;
}
接口扩展响应扩展基本响应{
扩展响应属性:对象;
}
函数返回响应(args:args):基本响应;
函数returnResponse(args:args&{callbackData:true}):ExtendedResponse;
函数returnResponse(args:args | args&{callbackData:true}):基本应答|扩展响应{
if(args为{callbackData:true}){
返回{ID:“foobar”,扩展响应属性:{}
}
返回{ID:“foobar”}
}
让res1=returnResponse({令牌:“asdf”,区域:“us”});
让res2=returnResponse({令牌:“foo”,callbackData:true});

消费者更容易阅读,因为它表明添加
callbackData:true
将返回不同的结果,但仍然不理想,因为它仍然是两种不同的参数类型。

如果您不喜欢重载,可以使用这样的泛型:

interface Args {
    token: string;
    region: string;
    extendedResponse?: true;
}

interface BasicResponse {
    ID: string;
}

interface ExtendedResponse extends BasicResponse {
    extendedResponseProperty: object;
}

function returnResponse<A extends Args>(args: A): A extends { extendedResponse: true} ? ExtendedResponse : BasicResponse {
    if (args.extendedResponse === true) {
        return { ID: "foobar", extendedResponseProperty: {} } as any;
    }

    return {ID: "foobar"} as any
}

let res1 = returnResponse({ token: "asdf", region: "us" });

let res2 = returnResponse({ token: "asdf", region: "asdf", extendedResponse: true });
接口参数{
令牌:字符串;
区域:字符串;
扩展响应?:true;
}
界面碱基应答{
ID:字符串;
}
接口扩展响应扩展基本响应{
扩展响应属性:对象;
}
函数returnResponse(args:A):扩展{extendedResponse:true}?扩展应答:基本应答{
if(args.extendedResponse===true){
返回{ID:“foobar”,extendedResponseProperty:{}如有;
}
返回{ID:“foobar”}
}
让res1=returnResponse({令牌:“asdf”,区域:“us”});
让res2=returnResponse({令牌:“asdf”,区域:“asdf”,extendedResponse:true});
但老实说,我喜欢你的代码沙盒中的代码。它描述了在没有额外魔法的情况下发生的事情,并且易于阅读

另外,我不确定你所说的“消费者将不得不处理方法过载”是什么意思——消费者得到了他们所调用的,而不是或多或少。您在这里描述的是一种特定的行为,无论您如何描述,不同的输入参数将导致不同的输出,并且一旦您的运行时代码这样做,使用者将不得不以任何方式处理这种行为