Tag extreme

by null @uid11

Take the Challenge

Despite the structural typing system in TypeScript, it is sometimes convenient to mark some types with tags, and so that these tags do not interfere with the ability to assign values of these types to each other. For example, using tags, you can check that some value passes through the calls of the required functions, and in the correct order: ```ts const doA = (x: T) => { const result = x return result as Tag } const doB = (x: T) => { const result = x return result as Tag }; const a = doA('foo') const b = doB(a) type Check0 = IsTrue> ``` Write a function `Tag` that takes a type `B` other than `null` and `undefined` and returns a type labeled with the string literal type `T`. The labeled types must be mutually assignable with the corresponding original types: ```ts declare let x: string declare let y: Tag x = y = x ``` When tagging a type already marked with a tag, a new tag must be added to the end of the list of all tags of the type: ```ts type T0 = Tag<{ foo: string }, 'A'> type T1 = Tag type Check1 = IsTrue> ``` Add some functions to check for type tags. `GetTags` retrieves a list of all tags of a type `B`: ```ts type T2 = Tag type Check2 = IsTrue, ['C']>> ``` `HasTag` checks if type `B` is tagged with tag `T` (and returns `true` or `false`): ```ts type T3 = Tag<0 | 1, 'D'> type Check3 = IsTrue> ``` `HasTags` checks if type `B` is tagged in succession with tags from tuple `T`: ```ts type T4 = Tag, 'B'>, 'C'> type Check4 = IsTrue> ``` `HasExactTags` checks if the list of all tags of type `B` is exactly equal to the `T` tuple: ```ts type T5 = Tag, 'B'> type Check5 = IsTrue> ``` Finally, add type `UnTag`, which removes all tags from type `B`: ```ts type T6 = Tag<{ bar: number }, 'A'> type T7 = UnTag type Check6 = IsFalse> ```
Back Share your Solutions Check out Solutions