[英]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.