簡體   English   中英

TypeScript - 基於參數類型的函數返回類型

[英]TypeScript - function return type based on parameter type

我得到了一些這樣的接口:

export interface BroadcastChannel {
  name: string;
  payload: Record<string, unknown>;
}

export interface TaskWindowCloseChannel extends BroadcastChannel {
  name: 'TASK_WINDOW_CLOSE';
  payload: {
    taskId: number;
  };
}

export interface WindowFocusChannel extends BroadcastChannel {
  name: 'WINDOW_FOCUS';
  payload: {
    windowName: string;
  };
}

將在函數中使用:

public listenChannel<T extends BroadcastChannel>(name:  T['name']): Observable<T> {
  const obs = new Subject<T>();
  const bc = new BroadcastChannel(name);
  bc.onmessage = (ev) => obs.next(ev.data);

  return obs.asObservable();
}

我想在這個函數上有一個類型邏輯,每當我在以前的接口中放置'TASK_WINDOW_CLOSE'name屬性的任何其他值時,我都會在 observable 中使用正確的payload屬性類型鍵入函數的返回類型。

我想避免過載,因為將來會有很多類似 TaskWindowChannel 的接口。

所以理想的輸出是:

listenChannel('TASK_WINDOW_CLOSE').subscribe((data: { taskId: number }) => {}); // data type is inferred by name param
listenChannel('WINDOW_FOCUS').subscribe((data: { windowName: string }) => {}); // data type is inferred by name param

你不能直接實現這個。 但是,您可以使用一個界面來“鏈接”您的有效負載和您的姓名

interface TaskWindowClosePayload{
    taskId: number,
}

interface WindowFocusPayload {
    windowName: string,
}

interface MapPayloadNameToType { 
    'TASK_WINDOW_CLOSE': TaskWindowClosePayload,
    'WINDOW_FOCUS': WindowFocusPayload,
}; 

interface MyBroadcastChannel<T extends keyof MapPayloadNameToType> {
    name: T;
    payload: MapPayloadNameToType[T]; 
}

現在您可以使用 const 字符串作為參數:

function foo<T extends keyof MapPayloadNameToType>(name: T): MyBroadcastChannel<T> {
    return null as any; // implement and make sure this is correct at runtime!
}

foo('TASK_WINDOW_CLOSE').payload.taskId;

這個想法是有一個類型,其中屬性是您的頻道名稱,屬性的類型是該頻道的有效負載的類型。 然后可以使用keyof關鍵字將這些鍵作為聯合類型獲取。

還可以看看 jcalz 上面的評論,他走相反的路線:從聯合類型構建名稱類型映射類型。

您可以通過引入更多類型(如type ChannelNames = keyof MapPayloadNameToType來增加一些便利,但這會使示例更加復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM