.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / type-fest / source / opaque.d.ts
1 /**
2 Create an opaque type, which hides its internal details from the public, and can only be created by being used explicitly.
3
4 The generic type parameter can be anything. It doesn't have to be an object.
5
6 [Read more about opaque types.](https://codemix.com/opaque-types-in-javascript/)
7
8 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:
9         - [Microsoft/TypeScript#15408](https://github.com/Microsoft/TypeScript/issues/15408)
10         - [Microsoft/TypeScript#15807](https://github.com/Microsoft/TypeScript/issues/15807)
11
12 @example
13 ```
14 import {Opaque} from 'type-fest';
15
16 type AccountNumber = Opaque<number, 'AccountNumber'>;
17 type AccountBalance = Opaque<number, 'AccountBalance'>;
18
19 // The Token parameter allows the compiler to differentiate between types, whereas "unknown" will not. For example, consider the following structures:
20 type ThingOne = Opaque<string>;
21 type ThingTwo = Opaque<string>;
22
23 // To the compiler, these types are allowed to be cast to each other as they have the same underlying type. They are both `string & { __opaque__: unknown }`.
24 // To avoid this behaviour, you would instead pass the "Token" parameter, like so.
25 type NewThingOne = Opaque<string, 'ThingOne'>;
26 type NewThingTwo = Opaque<string, 'ThingTwo'>;
27
28 // Now they're completely separate types, so the following will fail to compile.
29 function createNewThingOne (): NewThingOne {
30         // As you can see, casting from a string is still allowed. However, you may not cast NewThingOne to NewThingTwo, and vice versa.
31         return 'new thing one' as NewThingOne;
32 }
33
34 // This will fail to compile, as they are fundamentally different types.
35 const thingTwo = createNewThingOne() as NewThingTwo;
36
37 // Here's another example of opaque typing.
38 function createAccountNumber(): AccountNumber {
39         return 2 as AccountNumber;
40 }
41
42 function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance {
43         return 4 as AccountBalance;
44 }
45
46 // This will compile successfully.
47 getMoneyForAccount(createAccountNumber());
48
49 // But this won't, because it has to be explicitly passed as an `AccountNumber` type.
50 getMoneyForAccount(2);
51
52 // You can use opaque values like they aren't opaque too.
53 const accountNumber = createAccountNumber();
54
55 // This will not compile successfully.
56 const newAccountNumber = accountNumber + 2;
57
58 // As a side note, you can (and should) use recursive types for your opaque types to make them stronger and hopefully easier to type.
59 type Person = {
60         id: Opaque<number, Person>;
61         name: string;
62 };
63 ```
64 */
65 export type Opaque<Type, Token = unknown> = Type & {readonly __opaque__: Token};