typescript 如何使泛型类型可选?

pieyvz9o  于 2022-12-24  发布在  TypeScript
关注(0)|答案(7)|浏览(399)

我有以下日志记录方法:

private logData<T, S>(operation: string, responseData: T, requestData?: S) {
    this.logger.log(operation + ' ' + this.url);
    if (requestData) {
        this.logger.log('SENT');
        this.logger.log(requestData);
    }
    this.logger.log('RECEIVED');
    this.logger.log(responseData);
    return responseData;
}

requestData是可选的,我希望在不发送requestData到方法时,能够调用logData而不必指定S类型:而不是:this.logData<T, any>('GET', data),我想调用this.logData<T>('GET', data)
有没有办法做到这一点?

7cjasjjr

7cjasjjr1#

从TypeScript 2.3开始,您可以使用泛型参数默认值。

private logData<T, S = {}>(operation: string, responseData: T, requestData?: S) {
  // your implementation here
}
wfsdck30

wfsdck302#

2020年TS更新:给定void将使泛型类型可选。

type SomeType<T = void> = OtherType<T>;

上面的答案给出了一个默认值作为对象,使它成为可选的,但仍然给它赋值。
默认类型值的示例为{}

type BaseFunctionType<T1, T2> = (a:T1, b:T2) => void;

type FunctionType<T = {}> = BaseFunctionType<{name: string}, T>

const someFunction:FunctionType = (a) => {

}

someFunction({ name: "Siraj" });
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
// Expected 2 arguments, but got 1.(2554)

Playground链接
具有默认泛型类型值的示例为void

type BaseFunctionType<T1, T2> = (a:T1, b:T2) => void;

type FunctionType<T = void> = BaseFunctionType<{name: string}, T>

const someFunction:FunctionType = (a) => {

}

someFunction({ name: "Siraj" })

这是一本关于使泛型可选的好书。
Optional generic type in Typescript
Playground链接

nbnkbykc

nbnkbykc3#

根据TypeScript 2.2(您可以在TS Playground中尝试),调用this.logData("GET", data)data的类型为T)成功推断为this.logData<T, {}>("GET", data)
大卫Bohunek建议的重载可以在你使用的TS版本推理失败的情况下应用。无论如何,确保第二个签名在声明之前被定义,否则它将不会参与可用的重载。

// Declarations
private logData<T>(operation: string, responseData: T);
private logData<T, S>(operation: string, responseData: T, requestData?: S);
// Definition
private logData<T, S>(operation: string, responseData: T, requestData?: S) {
    // Body
}
3htmauhk

3htmauhk4#

如果您正在Type/Interface声明中查找可选泛型类型,这可能会有所帮助。
(came寻找这一点,只找到了处理泛型函数声明的答案。Siraj's answer让我走上了正确的道路。)

type ResponseWithMessage = {
  message: string;
};

interface ResponseWithData<T> extends ResponseWithMessage {
  data: T;
}

export type ResponseObject<T = void> = T extends void
  ? ResponseWithMessage
  : ResponseWithData<T>;
jckbn6z7

jckbn6z75#

部分怎么样?
构造类型的所有属性都设置为可选的类型。此实用工具将返回表示给定类型的所有子集的类型。

prdp8dxp

prdp8dxp6#

可以像这样编写重载方法:

private logData<T>(operation: string, responseData: T);
private logData<T, S>(operation: string, responseData: T, requestData?: S) {
    this.logger.log(operation + ' ' + this.url);
    if (requestData) {
        this.logger.log('SENT');
        this.logger.log(requestData);
    }
    this.logger.log('RECEIVED');
    this.logger.log(responseData);
    return responseData;
}

但是我认为你并不需要它,因为你不需要写this.logData<T, any>('GET', data),而只需要写this.logData('GET', data)T类型将被推断出来

cedebl8k

cedebl8k7#

  • void在需要某种类型的对象的地方不能很好地运行。运行得非常好,您只需要考虑void将覆盖您与之合并的任何内容(void & string基本上就是void)-这可能是您想要的
  • unknown
  • {}unknown基本相同
interface OffsetPagination {
    offset: number;
    limit: number;
}

interface PagePagination {
    page: number;
    size: number;
}

type HttpListParams<
    PaginationType extends OffsetPagination | PagePagination | void = void,
    Params = {
        filter?: string;
    },
> = PaginationType extends void ? Params : PaginationType & Params;

TSPlayground

相关问题