在TypeScript参数签名中处理潜在的空参数

在TypeScript参数签名中处理潜在的空参数,typescript,Typescript,在我的应用程序中,我有一个服务,它的方法被多次使用。一个方法接受一系列这样的参数(在我的示例中,参数的名称/指示是不相关的) 现在我需要扩展它,得到第四个可选参数,如下所示: doSomething(url: string, data: any, qParams?: QueryParams, headers?: HeadersType) {} 请注意,QueryParams和HeadersType是我编写的两种自定义类型。但是,在某些情况下,qParams将为空,并且标头将包含headersT

在我的应用程序中,我有一个服务,它的方法被多次使用。一个方法接受一系列这样的参数(在我的示例中,参数的名称/指示是不相关的)

现在我需要扩展它,得到第四个可选参数,如下所示:

doSomething(url: string, data: any, qParams?: QueryParams, headers?: HeadersType) {}
请注意,
QueryParams
HeadersType
是我编写的两种自定义类型。但是,在某些情况下,
qParams
将为空,并且标头将包含
headersType
对象。因此,在某些情况下,我将调用方法,如so
doSomething(urlValue,dataVal)
doSomething(urlVal,dataVal,qParamsVal)
doSomething(urlVal,dataVal,qParamsVal,headersVal)

当我想要使用
headersVal
而不是
qParamsVal
时,防止必须在参数列表中输入空值的最佳方法是什么。我意识到我可以用键传递一个对象,但我可以使用扩展操作符或其他东西。我使用的是TypeScript,我的应用程序是用Angular2编写的

非常感谢

请注意,QueryParams和HeadersType是我编写的两种自定义类型。[…]当我想要headersVal而不是qParamsVal时,防止在参数列表中输入空值的最佳方法是什么

在这种情况下,为
doSomething
创建附加值可能是可行的。这将使方法定义稍微复杂化,但会产生一个干净的调用签名:

// Callable signatures:
doSomething(url: string, data: any, qParams?: QueryParams);
doSomething(url: string, data: any, headers?: HeadersType);
doSomething(url: string, data: any, qParams?: QueryParams, headers?: HeadersType);

// Method implementation:
doSomething(url: string, data: any, qParamsOrHeaders?: QueryParams | HeadersType, headers?: HeadersType) {
    // The function body should determine which overload signature was used:
    if (qParamsOrHeaders instanceof QueryParams && headers instanceof HeadersType) {
        // used signature: (string, any, QueryParams, HeadersType)
        // ...
    } else if (qParamsOrHeaders instanceof HeadersType) {
        // used signature: (string, any, HeadersType)
        // ...
    } else if (qParamsOrHeaders instanceof QueryParams) {
        // used signature: (string, any, QueryParams)
        // ...
    } else {
        // used signature: (string, any)
        // ...
    }
}

显然,这要求
QueryParams
HeadersType
是实际的类类型。

当您有4个参数时,将它们作为具有4个属性的对象传递可能是有意义的,其中一些属性是可选的

您可以在调用时使用,也可以在定义方法时为参数使用,因此调用方法的各种方法如下所示

doSomething({url, data})  // when actual parameters names match args names exactly 

doSomething({url: urlVal, data: dataVal}); // when they don't

doSomething({url: urlVal, data: dataVal, qParams: qParamsVal});

doSomething({url: urlVal, data: dataVal, headers: headersVal}); 

doSomething({url, data, qParams, headers: headersVal});
您必须为参数定义一个接口,因此在定义函数时会有一些名称重复:

interface DoSomething {
    url: string;
    data: any; 
    qParams?: QueryParams;
    headers?: HeadersType;
}
doSomething({url, data, qParams, headers}: DoSomething): void {
    .... 
    if (qParams) {
        ....
    }
}
优点是参数总是被命名的,并且在调用方法时,您不必记住可选参数的确切顺序和插入的空值数量

interface DoSomething {
    url: string;
    data: any; 
    qParams?: QueryParams;
    headers?: HeadersType;
}
doSomething({url, data, qParams, headers}: DoSomething): void {
    .... 
    if (qParams) {
        ....
    }
}