--- /dev/null
+/**
+Create an opaque type, which hides its internal details from the public, and can only be created by being used explicitly.
+
+The generic type parameter can be anything. It doesn't have to be an object.
+
+[Read more about opaque types.](https://codemix.com/opaque-types-in-javascript/)
+
+There have been several discussions about adding this feature to TypeScript via the `opaque type` operator, similar to how Flow does it. Unfortunately, nothing has (yet) moved forward:
+ - [Microsoft/TypeScript#15408](https://github.com/Microsoft/TypeScript/issues/15408)
+ - [Microsoft/TypeScript#15807](https://github.com/Microsoft/TypeScript/issues/15807)
+
+@example
+```
+import {Opaque} from 'type-fest';
+
+type AccountNumber = Opaque<number>;
+type AccountBalance = Opaque<number>;
+
+function createAccountNumber(): AccountNumber {
+ return 2 as AccountNumber;
+}
+
+function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance {
+ return 4 as AccountBalance;
+}
+
+// This will compile successfully.
+getMoneyForAccount(createAccountNumber());
+
+// But this won't, because it has to be explicitly passed as an `AccountNumber` type.
+getMoneyForAccount(2);
+
+// You can use opaque values like they aren't opaque too.
+const accountNumber = createAccountNumber();
+
+// This will compile successfully.
+accountNumber + 2;
+```
+*/
+export type Opaque<Type> = Type & {readonly __opaque__: unique symbol};