簡體   English   中英

Typescript - 當參數為聯合時,從參數屬性繼承返回類型

[英]Typescript - inherit return type from the argument property when argument is union

我有一個類型,它是通用接口與 2 個通用類型的聯合。 其中一個是枚舉,另一個對於每個枚舉值都不同。

調用 function 時,TS 根據 function 調用中的枚舉值正確識別數據類型,但不明白返回值應該與 ZA8CFDE6331BD49EB2AC96F8911 的屬性之一相同的類型

代碼:

interface Base<D = any, T = string> {
  data: D;
  type: T;
}

enum BaseTypes {
  foo,
  bar,
  boo,
}

type BaseSet = Base<number, BaseTypes.foo> | Base<string, BaseTypes.bar> | Base<{d: number}, BaseType.boo>;

function processData(payload: BaseSet): typeof payload.data {
  return payload.data;
}

// a type should be number
// but it's number | string
const a = processData({ data: 1, type: BaseTypes.foo });

我的理解是a的類型應該從有效負載數據類型繼承,在這種情況下應該是string 我的兩個問題是:

  • 為什么它不起作用?
  • 我怎樣才能讓它工作?

問題:Function 不是通用的

processData function 不是通用的 function。 它接受一個 object 參數,該參數是兩種BaseSet類型中的一種。

它的返回類型為typeof payload.data 關鍵的區別是: payload的類型是什么? 在這個版本中, payload的類型是聯合類型BaseSet ,因此返回類型typeof payload.data payload.data 是BaseSet中所有data類型的聯合。

這是因為我們在執行processData(payload: BaseSet)時將payload的類型設置為BaseSet 如果我們有關於該payload變量類型的更具體信息,該信息就會丟失。 為了為payload保留更具體的類型,我們需要使用 generics。

解決方案:通用 Function

我們可以將processData設為通用 function 並說返回的類型取決於調用它的 arguments 的類型。 這里我使用泛型D來指代data屬性的類型。

function processData<D>(payload: BaseSet & {data: D}): D {
  return payload.data;
}

我們說payload必須具有類型{data: D}並且也是有效的BaseSet 這會強制執行配對,但也允許 typescript 推斷data的更具體的版本類型。 然后我們說這個特定的類型將是我們的返回類型。

測試它,我們得到正確的返回類型,如果datatype不匹配,也會出現錯誤。

const a = processData({ data: 1, type: BaseTypes.foo }); // number
const b = processData({ data: "hahaha", type: BaseTypes.foo }); // error
const c = processData({ data: "hahaha", type: BaseTypes.bar }); // string

Typescript 游樂場鏈接

有多種方法可以定義通用 function。 泛型是data類型還是整個payload類型? 我們應該對D應用任何約束還是& BaseSet就足夠了? 有趣的是,這個版本給了我文字字符串和數字作為返回類型。

function processData<D extends BaseSet['data']>(payload: BaseSet & {data: D}): D {
  return payload.data;
}
const a = processData({ data: 1, type: BaseTypes.foo }); // 1
const b = processData({ data: "hahaha", type: BaseTypes.foo }); // error
const c = processData({ data: "hahaha", type: BaseTypes.bar }); // "hahaha"

Typescript 游樂場鏈接

暫無
暫無

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

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