Tìm kiếm trang web

typescript - Làm sao để tôi có thể làm một kiểu generic trở thành tùy chọn?


Tôi có phương thức ghi nhật ký sau:

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 là tùy chọn. Tôi muốn có thể gọi logData mà không phải chỉ định kiểu S khi tôi không gửi requestData tới phương thức: thay vì: this.logData<T, any>('GET', data), tôi muốn gọi this.logData<T>('GET', data).

Có cách nào để đạt được điều này không?

Câu trả lời #1

Kể từ TypeScript 2.3, bạn có thể sử dụng các giá trị mặc định cho tham số tổng quát.

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

Câu trả lời #2

Cập nhật TS 2020: Việc đưa void sẽ khiến kiểu generic trở nên tùy chọn.

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

Câu trả lời ở trên, nơi một giá trị mặc định dưới dạng đối tượng được đưa ra, làm cho nó trở nên tùy chọn nhưng vẫn cung cấp giá trị cho nó.


Ví dụ với giá trị kiểu mặc định là {}:

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)

Liên kết Sân chơi


Ví dụ với giá trị kiểu tổng quát mặc định là 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" })

Đây là một bài đọc hay về cách làm cho generics trở nên tùy chọn.

Kiểu tổng quát tùy chọn trong Typescript

Liên kết Sân chơi

Câu trả lời #3

Theo TypeScript 2.2 (bạn có thể thử nó trong TS Playground), việc gọi this.logData("GET", data) (với data có kiểu T) được suy diễn thành công là this.logData<T, {}>("GET", data).

Sự nạp chồng được gợi ý bởi David Bohunek có thể được áp dụng nếu suy luận thất bại với phiên bản TS mà bạn sử dụng. Dù sao, hãy đảm bảo rằng chữ ký thứ hai được khai báo trước rồi mới định nghĩa, nếu không nó sẽ không tham gia vào các nạp chồng có sẵn.

// 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
}

Câu trả lời #4

Nếu bạn đang tìm một kiểu tổng quát tùy chọn trong khai báo Type/Interface, điều này có thể hữu ích.

(đã đến tìm cái này, chỉ tìm thấy các câu trả lời liên quan đến khai báo hàm chung. Câu trả lời của Siraj đã giúp tôi đi đúng hướng.)

type ResponseWithMessage = {
  message: string;
};

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

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

Bài viết liên quan