|
| 1 | +//// [tests/cases/compiler/divideAndConquerIntersections.ts] //// |
| 2 | + |
| 3 | +=== Performance Stats === |
| 4 | +Assignability cache: 100 / 100 (nearest 100) |
| 5 | +Type Count: 2,800 / 2,900 (nearest 100) |
| 6 | +Instantiation count: 7,500 / 7,500 (nearest 500) |
| 7 | +Symbol count: 26,000 / 26,000 (nearest 500) |
| 8 | + |
| 9 | +=== divideAndConquerIntersections.ts === |
| 10 | +type QQ<T extends string[]> = |
| 11 | +>QQ : QQ<T> |
| 12 | + |
| 13 | + & ("a" | T[0]) |
| 14 | + & ("b" | T[1]) |
| 15 | + & ("c" | T[2]) |
| 16 | + & ("d" | T[3]) |
| 17 | + & ("e" | T[4]) |
| 18 | + & ("f" | T[5]) |
| 19 | + & ("g" | T[6]) |
| 20 | + & ("h" | T[7]) |
| 21 | + & ("i" | T[8]) |
| 22 | + & ("j" | T[9]) |
| 23 | + & ("k" | T[10]) |
| 24 | + & ("l" | T[11]) |
| 25 | + & ("m" | T[12]) |
| 26 | + & ("n" | T[13]) |
| 27 | + & ("q" | T[14]) |
| 28 | + & ("p" | T[15]) |
| 29 | + & ("q" | T[16]) |
| 30 | + & ("r" | T[17]) |
| 31 | + & ("s" | T[18]) |
| 32 | + & ("t" | T[19]); |
| 33 | + |
| 34 | +// Repro from #57863 |
| 35 | + |
| 36 | +export interface Update { |
| 37 | + update_id: number; |
| 38 | +>update_id : number |
| 39 | + |
| 40 | + message?: { message: string }; |
| 41 | +>message : { message: string; } | undefined |
| 42 | +>message : string |
| 43 | + |
| 44 | + edited_message?: { edited_message: string }; |
| 45 | +>edited_message : { edited_message: string; } | undefined |
| 46 | +>edited_message : string |
| 47 | + |
| 48 | + channel_post?: { channel_post: string }; |
| 49 | +>channel_post : { channel_post: string; } | undefined |
| 50 | +>channel_post : string |
| 51 | + |
| 52 | + edited_channel_post?: { edited_channel_post: string }; |
| 53 | +>edited_channel_post : { edited_channel_post: string; } | undefined |
| 54 | +>edited_channel_post : string |
| 55 | + |
| 56 | + message_reaction?: { message_reaction: string }; |
| 57 | +>message_reaction : { message_reaction: string; } | undefined |
| 58 | +>message_reaction : string |
| 59 | + |
| 60 | + message_reaction_count?: { message_reaction_count: string }; |
| 61 | +>message_reaction_count : { message_reaction_count: string; } | undefined |
| 62 | +>message_reaction_count : string |
| 63 | + |
| 64 | + inline_query?: { inline_query: string }; |
| 65 | +>inline_query : { inline_query: string; } | undefined |
| 66 | +>inline_query : string |
| 67 | + |
| 68 | + chosen_inline_result?: { chosen_inline_result: string }; |
| 69 | +>chosen_inline_result : { chosen_inline_result: string; } | undefined |
| 70 | +>chosen_inline_result : string |
| 71 | + |
| 72 | + callback_query?: { callback_query: string }; |
| 73 | +>callback_query : { callback_query: string; } | undefined |
| 74 | +>callback_query : string |
| 75 | + |
| 76 | + shipping_query?: { shipping_query: string }; |
| 77 | +>shipping_query : { shipping_query: string; } | undefined |
| 78 | +>shipping_query : string |
| 79 | + |
| 80 | + pre_checkout_query?: { pre_checkout_query: string }; |
| 81 | +>pre_checkout_query : { pre_checkout_query: string; } | undefined |
| 82 | +>pre_checkout_query : string |
| 83 | + |
| 84 | + poll?: { poll: string }; |
| 85 | +>poll : { poll: string; } | undefined |
| 86 | +>poll : string |
| 87 | + |
| 88 | + poll_answer?: { poll_answer: string }; |
| 89 | +>poll_answer : { poll_answer: string; } | undefined |
| 90 | +>poll_answer : string |
| 91 | + |
| 92 | + my_chat_member?: { my_chat_member: string }; |
| 93 | +>my_chat_member : { my_chat_member: string; } | undefined |
| 94 | +>my_chat_member : string |
| 95 | + |
| 96 | + chat_member?: { chat_member: string }; |
| 97 | +>chat_member : { chat_member: string; } | undefined |
| 98 | +>chat_member : string |
| 99 | + |
| 100 | + chat_join_request?: { chat_join_request: string }; |
| 101 | +>chat_join_request : { chat_join_request: string; } | undefined |
| 102 | +>chat_join_request : string |
| 103 | + |
| 104 | + chat_boost?: { chat_boost: string }; |
| 105 | +>chat_boost : { chat_boost: string; } | undefined |
| 106 | +>chat_boost : string |
| 107 | + |
| 108 | + removed_chat_boost?: { removed_chat_boost: string }; |
| 109 | +>removed_chat_boost : { removed_chat_boost: string; } | undefined |
| 110 | +>removed_chat_boost : string |
| 111 | +} |
| 112 | + |
| 113 | +type FilterFunction<U extends Update, V extends U> = (up: U) => up is V; |
| 114 | +>FilterFunction : FilterFunction<U, V> |
| 115 | +>up : U |
| 116 | + |
| 117 | +export function matchFilter<U extends Update, Q extends FilterQuery>( |
| 118 | +>matchFilter : <U extends Update, Q extends "message" | "edited_message" | "channel_post" | "edited_channel_post" | "message_reaction" | "message_reaction_count" | "inline_query" | "chosen_inline_result" | "callback_query" | "shipping_query" | "pre_checkout_query" | "poll" | "poll_answer" | "my_chat_member" | "chat_member" | "chat_join_request" | "chat_boost" | "removed_chat_boost">(filter: Q | Q[]) => FilterFunction<U, Filter<U, Q>> |
| 119 | + |
| 120 | + filter: Q | Q[], |
| 121 | +>filter : Q | Q[] |
| 122 | + |
| 123 | +): FilterFunction<U, Filter<U, Q>> { |
| 124 | + // ^ errors out |
| 125 | + console.log("Matching", filter); |
| 126 | +>console.log("Matching", filter) : void |
| 127 | +>console.log : (...data: any[]) => void |
| 128 | +>console : Console |
| 129 | +>log : (...data: any[]) => void |
| 130 | +>"Matching" : "Matching" |
| 131 | +>filter : "message" | "edited_message" | "channel_post" | "edited_channel_post" | "message_reaction" | "message_reaction_count" | "inline_query" | "chosen_inline_result" | "callback_query" | "shipping_query" | "pre_checkout_query" | "poll" | "poll_answer" | "my_chat_member" | "chat_member" | "chat_join_request" | "chat_boost" | "removed_chat_boost" | Q[] |
| 132 | + |
| 133 | + return (up: U): up is Filter<U, Q> => !!up; |
| 134 | +>(up: U): up is Filter<U, Q> => !!up : (up: U) => up is PerformQuery<U, Combine<L1Fragment<Q>, Q>> |
| 135 | +>up : U |
| 136 | +>!!up : true |
| 137 | +>!up : false |
| 138 | +>up : U |
| 139 | +} |
| 140 | + |
| 141 | +/** All valid filter queries (every update key except update_id) */ |
| 142 | +export type FilterQuery = keyof Omit<Update, "update_id">; |
| 143 | +>FilterQuery : "message" | "edited_message" | "channel_post" | "edited_channel_post" | "message_reaction" | "message_reaction_count" | "inline_query" | "chosen_inline_result" | "callback_query" | "shipping_query" | "pre_checkout_query" | "poll" | "poll_answer" | "my_chat_member" | "chat_member" | "chat_join_request" | "chat_boost" | "removed_chat_boost" |
| 144 | + |
| 145 | +/** Narrow down an update object based on a filter query */ |
| 146 | +export type Filter<U extends Update, Q extends FilterQuery> = PerformQuery< |
| 147 | +>Filter : Filter<U, Q> |
| 148 | + |
| 149 | + U, |
| 150 | + RunQuery<Q> |
| 151 | +>; |
| 152 | + |
| 153 | +// generate an object structure that can be intersected with updates to narrow them down |
| 154 | +type RunQuery<Q extends string> = Combine<L1Fragment<Q>, Q>; |
| 155 | +>RunQuery : RunQuery<Q> |
| 156 | + |
| 157 | +// maps each part of the filter query to Record<"key", object> |
| 158 | +type L1Fragment<Q extends string> = Q extends unknown ? Record<Q, object> |
| 159 | +>L1Fragment : L1Fragment<Q> |
| 160 | + |
| 161 | + : never; |
| 162 | +// define all other fields from query as keys with value `undefined` |
| 163 | +type Combine<U, K extends string> = U extends unknown |
| 164 | +>Combine : Combine<U, K> |
| 165 | + |
| 166 | + ? U & Partial<Record<Exclude<K, keyof U>, undefined>> |
| 167 | + : never; |
| 168 | + |
| 169 | +// apply a query result by intersecting it with update, |
| 170 | +// and then using these values to override the actual update |
| 171 | +type PerformQuery<U extends Update, R extends object> = R extends unknown |
| 172 | +>PerformQuery : PerformQuery<U, R> |
| 173 | + |
| 174 | + ? FilteredEvent<U, Update & R> |
| 175 | + : never; |
| 176 | + |
| 177 | +// narrow down an update by intersecting it with a different update |
| 178 | +type FilteredEvent<E extends Update, U extends Update> = |
| 179 | +>FilteredEvent : FilteredEvent<E, U> |
| 180 | + |
| 181 | + & E |
| 182 | + & Omit<U, "update_id">; |
| 183 | + |
| 184 | +type Middleware<U extends Update> = (ctx: U) => unknown | Promise<unknown>; |
| 185 | +>Middleware : Middleware<U> |
| 186 | +>ctx : U |
| 187 | + |
| 188 | +class EventHub<U extends Update> { |
| 189 | +>EventHub : EventHub<U> |
| 190 | + |
| 191 | + use(...middleware: Array<Middleware<U>>): EventHub<U> { |
| 192 | +>use : (...middleware: Array<Middleware<U>>) => EventHub<U> |
| 193 | +>middleware : Middleware<U>[] |
| 194 | + |
| 195 | + console.log("Adding", middleware.length, "generic handlers"); |
| 196 | +>console.log("Adding", middleware.length, "generic handlers") : void |
| 197 | +>console.log : (...data: any[]) => void |
| 198 | +>console : Console |
| 199 | +>log : (...data: any[]) => void |
| 200 | +>"Adding" : "Adding" |
| 201 | +>middleware.length : number |
| 202 | +>middleware : Middleware<U>[] |
| 203 | +>length : number |
| 204 | +>"generic handlers" : "generic handlers" |
| 205 | + |
| 206 | + return this; |
| 207 | +>this : this |
| 208 | + } |
| 209 | + on<Q extends FilterQuery>( |
| 210 | +>on : <Q extends "message" | "edited_message" | "channel_post" | "edited_channel_post" | "message_reaction" | "message_reaction_count" | "inline_query" | "chosen_inline_result" | "callback_query" | "shipping_query" | "pre_checkout_query" | "poll" | "poll_answer" | "my_chat_member" | "chat_member" | "chat_join_request" | "chat_boost" | "removed_chat_boost">(filter: Q | Q[], ...middleware: Array<Middleware<Filter<U, Q>>>) => EventHub<Filter<U, Q>> |
| 211 | + |
| 212 | + filter: Q | Q[], |
| 213 | +>filter : Q | Q[] |
| 214 | + |
| 215 | + ...middleware: Array<Middleware<Filter<U, Q>>> |
| 216 | +>middleware : Middleware<PerformQuery<U, Combine<L1Fragment<Q>, Q>>>[] |
| 217 | + |
| 218 | + // ^ errors out |
| 219 | + ): EventHub<Filter<U, Q>> { |
| 220 | + console.log("Adding", middleware.length, "handlers for", filter); |
| 221 | +>console.log("Adding", middleware.length, "handlers for", filter) : void |
| 222 | +>console.log : (...data: any[]) => void |
| 223 | +>console : Console |
| 224 | +>log : (...data: any[]) => void |
| 225 | +>"Adding" : "Adding" |
| 226 | +>middleware.length : number |
| 227 | +>middleware : Middleware<PerformQuery<U, Combine<L1Fragment<Q>, Q>>>[] |
| 228 | +>length : number |
| 229 | +>"handlers for" : "handlers for" |
| 230 | +>filter : "message" | "edited_message" | "channel_post" | "edited_channel_post" | "message_reaction" | "message_reaction_count" | "inline_query" | "chosen_inline_result" | "callback_query" | "shipping_query" | "pre_checkout_query" | "poll" | "poll_answer" | "my_chat_member" | "chat_member" | "chat_join_request" | "chat_boost" | "removed_chat_boost" | Q[] |
| 231 | + |
| 232 | + return new EventHub<Filter<U, Q>>(); |
| 233 | +>new EventHub<Filter<U, Q>>() : EventHub<PerformQuery<U, Combine<L1Fragment<Q>, Q>>> |
| 234 | +>EventHub : typeof EventHub |
| 235 | + } |
| 236 | +} |
| 237 | + |
0 commit comments