Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions include/customDefinitions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,33 @@ interface Instance extends RBXObject {
Clone<T extends Instance>(this: T): T;
GetActor(this: Instance): Actor | undefined;
GetDescendants(this: Instance): Array<Instance>;
/**
* Returns an array of all descendants matching the given selector string.
*
* **Selectors**
* - `ClassName` — matches via `IsA` (e.g. `"BasePart"`)
* - `.Tag` — CollectionService tag (e.g. `".Fruit"`)
* - `#Name` — exact `Instance.Name` (e.g. `"#MyPart"`)
* - `[property = value]` — property value match (e.g. `"[CanCollide = false]"`)
* - `[$attribute]` — attribute presence (e.g. `"[$FuelCapacity]"`)
* - `[$attribute = value]` — attribute value match (e.g. `"[$FuelCapacity = 75]"`)
*
* Selectors can be freely combined, e.g. `"Model.Apple[$Variety = Fuji]"`.
*
* **Combinators**
* - `A > B` — `B` must be a *direct child* of `A`
* - `A >> B` — `B` must be a *descendant* of `A` (implicit default)
* - `A, B` — union; returns matches from both selectors
*
* **Pseudo-classes**
* - `:not(sel, ...)` — excludes matches (e.g. `":not(SpotLight, PointLight)"`)
* - `:has(rel-sel)` — keeps instances that contain a matching descendant (e.g. `":has(Tool)"`)
*
* The return type is automatically narrowed when the selector begins with a known Roblox class
* name. For example `QueryDescendants("Part#MyPart")` returns `Array<Part>` and
* `QueryDescendants("Part, SpotLight")` returns `Array<Part | SpotLight>`.
*/
QueryDescendants<S extends string>(this: Instance, selector: S): Array<_QueryDescendantsResult<S>>;
GetTags(this: Instance): Array<string>;
FindFirstChild(this: Instance, childName: string | number, recursive?: boolean): Instance | undefined;
WaitForChild(this: Instance, childName: string | number): Instance;
Expand Down
49 changes: 49 additions & 0 deletions include/roblox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,55 @@ interface RBXScriptSignal<T extends Callback = Callback> {
interface Instances {}
interface CreatableInstances {}

/** @internal Trim leading spaces from a selector string literal type. */
type _TrimLeft<S extends string> = S extends ` ${infer R}` ? _TrimLeft<R> : S;

/** @internal Strip a leading `>> ` or `> ` combinator from an already-trimmed token. */
type _StripLeadingCombinator<S extends string> = S extends `>> ${infer R}` ? R : S extends `> ${infer R}` ? R : S;

/**
* @internal The leading Roblox class name of a simple selector token.
* Splits at the first `:` `.` `#` `[` or ` `, returning `""` when the token starts with one of those characters.
* Checking `:` first ensures `Part:has(...)` yields `"Part"` rather than splitting at a nested `.`.
*/
type _SelectorLeadingClass<S extends string> = S extends `${infer C}:${string}`
? C
: S extends `${infer C}.${string}`
? C
: S extends `${infer C}#${string}`
? C
: S extends `${infer C}[${string}`
? C
: S extends `${infer C} ${string}`
? C
: S;

/**
* @internal The final simple-selector segment after following all top-level combinators.
* `${string} >> ` / `${string} > ` are greedy, so they match the *last* combinator in the string.
* After a ` >> ` split, any remaining ` > ` is also resolved, covering two-level chains.
* Combinators inside `:has(> …)` are safe: the outer grammar requires a space before `>` / `>>`,
* whereas the inner grammar writes `(>` with no preceding space.
*/
type _TrailingSegment<S extends string> = S extends `${string} >> ${infer R}`
? R extends `${string} > ${infer T}`
? _StripLeadingCombinator<_TrimLeft<T>>
: _StripLeadingCombinator<_TrimLeft<R>>
: S extends `${string} > ${infer R}`
? _StripLeadingCombinator<_TrimLeft<R>>
: _StripLeadingCombinator<_TrimLeft<S>>;

/** @internal Resolves a complex selector to the narrowest `Instance` subtype it can produce. */
type _ResolveComplexSelector<S extends string> =
_SelectorLeadingClass<_TrailingSegment<S>> extends infer C extends keyof Instances ? Instances[C] : Instance;

/** @internal Union of result types for a comma-separated selector list. */
type _QueryDescendantsResult<S extends string> = S extends `${infer A}, ${infer B}`
? _ResolveComplexSelector<A> | _QueryDescendantsResult<B>
: S extends `${infer A},${infer B}`
? _ResolveComplexSelector<A> | _QueryDescendantsResult<B>
: _ResolveComplexSelector<S>;

// InstanceConstructor
interface InstanceConstructor {
/**
Expand Down
Loading