在TypeScript参数签名中处理可能为空的参数

3
在我的应用程序中,我有一个服务,其中的方法被多次使用。一个方法会传递一系列参数,如下所示(在我的例子中,参数的名称/指示是无关紧要的)...
doSomething(url: string, data: any, qParams?: QueryParams) {}

现在我需要扩展它以接受第四个可选参数,如下所示:
doSomething(url: string, data: any, qParams?: QueryParams, headers?: HeadersType) {}

请注意,QueryParamsHeadersType 是我编写的两个自定义类型。但是有些情况下,qParams 会为 null,头部信息将包含一个 headersType 对象。因此,在某些情况下,我将以以下方式调用方法:doSomething(urlValue, dataVal)doSomething(urlVal, dataVal, qParamsVal)doSomething(urlVal, dataVal, null, headersVal)doSomething(urlVal, dataVal, qParamsVal, headersVal)
有什么最好的方法可以避免在想要使用 headersVal 而不是 qParamsVal 的参数列表中放置 null 值呢?我意识到我可以传递一个带有键的对象,但我是否可以使用展开运算符或其他内容。我正在使用 TypeScript,并且我的应用程序是使用 Angular2 编写的。
非常感谢。
2个回答

2
当你有四个参数时,将它们作为一个具有四个属性的对象传递可能是有意义的,其中一些是可选的。
在调用时,您可以使用简写对象字面量,并在定义方法时使用对象解构来获取参数,因此调用该方法的各种方式将看起来像:
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) {
        ....
    }
}

优点在于参数总是有名称,当调用方法时,您不必记住确切的顺序和要插入多少个空值来表示可选参数。

1
请注意,QueryParams和HeadersType是我编写的两种自定义类型。[...] 当我想要headersVal但不想要qParamsVal时,如何最好地避免将null值放入参数列表中?
在这种情况下,创建额外的overload signatures可能是可行的。它会稍微复杂化方法定义,但会产生一个清晰的调用签名:
// 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)
        // ...
    }
}

显然,这需要QueryParamsHeadersType是实际的类类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接