簡體   English   中英

如何在 TypeScript 中定義不透明類型?

[英]How to define an opaque type in TypeScript?

如果我沒記錯的話,在 C++ 中你可以定義一個像這樣的不透明類型......

class Foo;

...並像句柄一樣使用它,例如在聲明函數簽名時...

void printFoo(const Foo& foo);

然后,應用程序代碼可能會在沒有看到 Foo 的實際定義的情況下使用對 Foo 的引用或對 Foo 的指針。

TypeScript 中是否有類似的東西——你會如何定義一個不透明的類型?

我的問題是,如果我定義這個......

interface Foo {};

...然后可以與其他類似類型自由互換。 有成語嗎?

那是因為 TypeScript 類型系統是“結構化的”,因此任何具有相同形狀的兩種類型都可以相互分配——而不是“名義”,在這種情況下,引入像Foo這樣的新名稱將使其不可分配給相同的-shape Bar類型,反之亦然。

跟蹤 TS 的名義類型添加是一個長期存在的問題

TS 中 opaque 類型的一種常見近似是使用唯一的標簽來使任何兩種類型在結構上不同:

// opaque type module:
export type EUR = { readonly _tag: 'EUR' };
export function eur(value: number): EUR {
  return value as any;
}
export function addEuros(a: EUR, b: EUR): EUR {
  return ((a as any) + (b as any)) as any;
}

// usage from other modules:
const result: EUR = addEuros(eur(1), eur(10)); // OK
const c = eur(1) + eur(10) // Error: Operator '+' cannot be applied to types 'EUR' and 'EUR'.

更好的是,標簽可以用唯一的 Symbol 進行編碼,以確保它永遠不會被訪問和使用:

declare const tag: unique symbol;
export type EUR = { readonly [tag]: 'EUR' };

請注意,這些表示在運行時沒有任何影響,唯一的開銷是調用eur構造函數。

newtype-ts提供了通用實用程序,用於定義和使用行為類似於我上面的示例的類型的值。

品牌類型

另一個典型用例是僅在一個方向上保持不可分配性,即處理可分配給numberEUR類型:

declare const a: EUR;
const b: number = a; // OK

這可以通過所謂的“品牌類型”獲得:

declare const tag: unique symbol
export type EUR = number & { readonly [tag]: 'EUR' };

例如,在io-ts庫中查看這種用法。

暫無
暫無

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

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