[英]Is it possible to have multiple return types for a generic Typescript function?
我目前正在設計一個帶有 Typescript 的 web 服務器並且遇到了死胡同。 目標是有一個接口或類似的東西,讓任何其他沒有深入了解系統 rest 的開發人員進來,實現他們自己的解析器版本,並讓它與系統的 rest 一起工作。 此外,我希望可以選擇在不修改原始代碼的情況下添加更多返回類型。
目前,我已經定義了數據的形狀,並且我正試圖將我的頭繞在解析器本身上。 數據如下所示:
export namespace CardData {
export interface Base {
type: string;
source: Source;
}
export interface Graph {
labels: string[];
data: number[];
}
// Other definitions below
}
解析器界面如下所示:
export interface Source {
id: number;
name: string;
url: string;
isReachable: boolean;
type: string;
}
export interface ConnectorArgument {
id: number;
key: string;
value: string;
}
export interface Parser {
// Unrelated code
// The type of T depends on args
getSource: <T>(
source: Source,
args: ConnectorArgument[]
) => Promise<T>;
}
但是如果我實現 getSource 並嘗試返回任何東西,我會得到:
'T' could be instantiated with an arbitrary type which could be unrelated to 'Graph'.
我理解為什么 Typescript 拒絕讓這個工作,因為 T 的類型是由 function 的調用者確定的,但我還沒有想出一個好的替代方案。
我已經查看了其他問題,例如此處和此處,但沒有一個真正適合我的問題。 這甚至可以在 Typescript 中做到,還是我最好使用其他語言?
編輯 1:我添加了 Source 和 ConnectorArgument 的定義。
由於source
arg 中的字符串type
屬性應確定整體返回類型,因此有一個 TypeScript 范例可以處理此映射。 如果您想查閱更廣泛的示例,它與 typeScript 的 DOM 聲明中的addEventListener
及其親屬使用的相同。
在您的情況下,您需要在type
字符串值和將為它們返回的實際類型之間創建一個 map 接口。 getSource
的返回類型將是從該 map 中查找的內容。 不幸的是,由於此處描述的 TypeScript 中的一些限制,在返回每種可能的類型時需要進行不雅的轉換。 以下是它的外觀(以更簡單的結構為例):
interface Widget { foo: number }
interface Sprocket { bar: number }
interface SourceTypeMap {
'widget': Widget;
'sprocket': Sprocket;
}
interface Source {
type: keyof SourceTypeMap;
}
interface Parser {
getSource: <T extends keyof SourceTypeMap>(
source: Source & { type: T }
) => Promise<SourceTypeMap[T]>;
}
class ExampleParser implements Parser {
async getSource<T extends keyof SourceTypeMap>(
source: Source & { type: T }
): Promise<SourceTypeMap[T]> {
return ((): SourceTypeMap[keyof SourceTypeMap] =>
{
switch (source.type) {
case 'widget':
return { foo: 42 };
case 'sprocket':
return { bar: 42 };
}
throw new TypeError(`unsupported type '${source.type}'`);
}) () as SourceTypeMap[T];
}
}
async function test() {
const parser = new ExampleParser ();
const widget = await parser.getSource({ type: 'widget' }); // infers Widget type
console.log(widget); // { foo: 42 }
const sprocket = await parser.getSource({ type: 'sprocket' }); // infers Sprocket type
console.log(sprocket); // { bar: 42 }
}
test();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.