@rbxts/types 1.0.936 → 1.0.938

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,152 @@
1
+ /// <reference no-default-lib="true"/>
2
+
3
+ /**
4
+ * Resolves the selector strings accepted by `Instance:QueryDescendants()` to the type of the
5
+ * instances they match, so string-literal selectors get a precise return type. The grammar is
6
+ * documented at https://create.roblox.com/docs/reference/engine/classes/Instance#QueryDescendants
7
+ *
8
+ * Only the class named in the last combinator segment affects the result, unioned across
9
+ * comma-separated selectors. `.Tag` and `#Name` carry no class information and resolve to
10
+ * `Instance`; attribute filters and pseudo-classes never change the class. Note that
11
+ * whitespace is not a combinator in this grammar (descendant matching is `>>`), so spaces
12
+ * are ignored rather than treated as separators.
13
+ */
14
+ declare namespace Selector {
15
+ type Trim<T extends string> = T extends `${infer S} ` ? Trim<S> : T extends ` ${infer S}` ? Trim<S> : T;
16
+
17
+ type SolveHead<Head extends string | undefined> = Head extends string
18
+ ? Trim<Head> extends infer C extends keyof Instances
19
+ ? Instances[C]
20
+ : Instance
21
+ : Instance;
22
+
23
+ type AddSolvedHead<Result, Head extends string | undefined> = [Result] extends [never]
24
+ ? SolveHead<Head>
25
+ : Result | SolveHead<Head>;
26
+
27
+ type HeadBreak = ":" | "." | "#" | "[" | " ";
28
+
29
+ type ReadHead<
30
+ Head extends string | undefined = undefined,
31
+ Done extends boolean = false,
32
+ C extends string = "",
33
+ > = Done extends true
34
+ ? [Head, Done]
35
+ : Head extends undefined
36
+ ? Trim<C> extends ""
37
+ ? [undefined, false]
38
+ : C extends HeadBreak
39
+ ? ["", true]
40
+ : [C, false]
41
+ : C extends HeadBreak
42
+ ? [Head, true]
43
+ : [`${Head}${C}`, false];
44
+
45
+ type SolveChars<
46
+ S extends string,
47
+ Head extends string | undefined = undefined,
48
+ Done extends boolean = false,
49
+ Result = never,
50
+ Depth extends Array<any> = [],
51
+ > = S extends `${infer C}${infer Rest}`
52
+ ? Depth extends []
53
+ ? C extends "("
54
+ ? SolveChars<Rest, Head, Done, Result, [any]>
55
+ : C extends ","
56
+ ? SolveChars<Rest, undefined, false, AddSolvedHead<Result, Head>, Depth>
57
+ : C extends ">"
58
+ ? SolveChars<Rest, undefined, false, Result, Depth>
59
+ : ReadHead<Head, Done, C> extends [
60
+ infer NextHead extends string | undefined,
61
+ infer NextDone extends boolean,
62
+ ]
63
+ ? SolveChars<Rest, NextHead, NextDone, Result, Depth>
64
+ : never
65
+ : C extends "("
66
+ ? SolveChars<Rest, Head, Done, Result, [...Depth, any]>
67
+ : C extends ")"
68
+ ? SolveChars<Rest, Head, Done, Result, Depth extends [any, ...infer D] ? D : []>
69
+ : SolveChars<Rest, Head, Done, Result, Depth>
70
+ : AddSolvedHead<Result, Head>;
71
+
72
+ // Nested pseudo-classes can contain selector lists, so this path tracks only top-level
73
+ // separators while keeping the subject class from the current segment.
74
+ type SlowSolve<T extends string> = SolveChars<T>;
75
+
76
+ // Only the final combinator segment can determine the subject type.
77
+ type LastSegment<S extends string> = S extends `${string}>${infer R}` ? LastSegment<R> : S;
78
+
79
+ type CutAt<S extends string, D extends string> = S extends `${infer Prefix}${D}${string}` ? Prefix : S;
80
+
81
+ type LeadingClass<S extends string> = CutAt<CutAt<CutAt<CutAt<Trim<S>, ":">, ".">, "#">, " ">;
82
+
83
+ // Filters do not affect the subject class, but their values can contain selector separators.
84
+ type StripFiltersAndParens<S extends string> = S extends `${infer A}[${string}]${infer B}`
85
+ ? StripFiltersAndParens<`${A}${B}`>
86
+ : S extends `${infer A}(${string})${infer B}`
87
+ ? StripFiltersAndParens<`${A}${B}`>
88
+ : S;
89
+
90
+ type FastClause<S extends string> =
91
+ LeadingClass<LastSegment<S>> extends infer C extends keyof Instances ? Instances[C] : Instance;
92
+
93
+ type FastSolve<S extends string> = S extends `${infer A},${infer B}` ? FastClause<A> | FastSolve<B> : FastClause<S>;
94
+
95
+ type SolveUnquoted<S extends string> = S extends `${string}(${string}(${string})${string})${string}`
96
+ ? SlowSolve<S>
97
+ : FastSolve<StripFiltersAndParens<S>>;
98
+
99
+ type StripQuotes<S extends string> = S extends `${infer A}'${string}'${infer B}` ? StripQuotes<`${A}${B}`> : S;
100
+
101
+ // Attribute values are not selector syntax, even when they contain ":" or ",".
102
+ type StripValidationGroups<S extends string> = S extends `${infer A}'${string}'${infer B}`
103
+ ? StripValidationGroups<`${A}${B}`>
104
+ : S extends `${infer A}[${string}]${infer B}`
105
+ ? StripValidationGroups<`${A}${B}`>
106
+ : S;
107
+
108
+ type SupportedPseudo = "not" | "has";
109
+
110
+ type CheckPseudos<S extends string> = S extends `${string}:${infer R}`
111
+ ? R extends `${infer Name}(${infer Rest}`
112
+ ? Name extends SupportedPseudo
113
+ ? CheckPseudos<Rest>
114
+ : Name
115
+ : R // ':' not followed by 'name(' -> pseudo-classes require arguments
116
+ : never;
117
+
118
+ // The whole-empty selector "" is intentionally allowed.
119
+ type HasEmptyListItem<S extends string> = S extends `${string},${string}` ? CheckListItems<S> : false;
120
+ type CheckListItems<S extends string> = S extends `${infer A},${infer B}`
121
+ ? Trim<A> extends ""
122
+ ? true
123
+ : CheckListItems<B>
124
+ : Trim<S> extends ""
125
+ ? true
126
+ : false;
127
+
128
+ type ValidateUnquoted<S extends string, Q extends string> = Q extends `${string}:${string}`
129
+ ? CheckPseudos<Q> extends infer Bad
130
+ ? [Bad] extends [never]
131
+ ? HasEmptyListItem<Q> extends true
132
+ ? `Invalid selector: empty selector in list (check for a stray or trailing comma)`
133
+ : S
134
+ : `Invalid selector: ':${Bad & string}' is not a supported pseudo-class (only ':not()' and ':has()' are allowed)`
135
+ : never
136
+ : Q extends `${string},${string}`
137
+ ? HasEmptyListItem<Q> extends true
138
+ ? `Invalid selector: empty selector in list (check for a stray or trailing comma)`
139
+ : S
140
+ : S;
141
+
142
+ export type ValidateSelector<S extends string> = string extends S
143
+ ? S
144
+ : StripValidationGroups<S> extends infer Q extends string
145
+ ? ValidateUnquoted<S, Q>
146
+ : never;
147
+
148
+ // Quoted values are stripped before solving so most selectors can stay on the cheaper path.
149
+ export type Solve<S extends string> = S extends `${string}'${string}`
150
+ ? SolveUnquoted<StripQuotes<S>>
151
+ : SolveUnquoted<S>;
152
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/types",
3
- "version": "1.0.936",
3
+ "version": "1.0.938",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },