Skip to content

Commit

Permalink
Infer virtual type definition from renderer arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
megheaiulian committed Feb 21, 2025
1 parent 3bdc4b0 commit 4705ede
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-mammals-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"haunted": minor
---

Infer `virtual` type definition from renderer arguments.
58 changes: 38 additions & 20 deletions src/virtual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@ import {
DirectiveParameters,
ChildPart,
PartInfo,
} from "lit-html/directive.js";
import { noChange } from "lit-html";
import { AsyncDirective } from "lit-html/async-directive.js";
} from "lit/directive.js";
import { noChange } from "lit";
import { AsyncDirective } from "lit/async-directive.js";
import { GenericRenderer } from "./core";
import { BaseScheduler } from "./scheduler";

const includes = Array.prototype.includes;

interface Renderer extends GenericRenderer<ChildPart> {
(this: ChildPart, ...args: unknown[]): unknown | void;
interface Renderer<T extends unknown[]> extends GenericRenderer<ChildPart> {
(this: ChildPart, ...args: T): unknown | void;
}

const partToScheduler: WeakMap<ChildPart, Scheduler> = new WeakMap();
const schedulerToPart: WeakMap<Scheduler, ChildPart> = new WeakMap();
const partToScheduler: WeakMap<ChildPart, Scheduler<any>> = new WeakMap();
const schedulerToPart: WeakMap<Scheduler<any>, ChildPart> = new WeakMap();

class Scheduler extends BaseScheduler<object, ChildPart, Renderer, ChildPart> {
args!: unknown[];
class Scheduler<T extends unknown[]> extends BaseScheduler<
object,
ChildPart,
Renderer<T>,
ChildPart
> {
args!: T;
setValue: Function;

constructor(renderer: Renderer, part: ChildPart, setValue: Function) {
constructor(renderer: Renderer<T>, part: ChildPart, setValue: Function) {
super(renderer, part);
this.state.virtual = true;
this.setValue = setValue;
Expand All @@ -43,10 +48,19 @@ class Scheduler extends BaseScheduler<object, ChildPart, Renderer, ChildPart> {
}
}

function makeVirtual(): any {
function virtual(renderer: Renderer) {
interface VirtualRenderer<T extends unknown[]> {
(this: ChildPart, ...args: T): unknown | void;
}
export interface Virtual {
<T extends unknown[]>(renderer: VirtualRenderer<T>): (
...values: T
) => unknown;
}

function makeVirtual(): Virtual {
function virtual<T extends unknown[]>(renderer: VirtualRenderer<T>) {
class VirtualDirective extends AsyncDirective {
cont: Scheduler | undefined;
cont: Scheduler<T> | undefined;

constructor(partInfo: PartInfo) {
super(partInfo);
Expand All @@ -56,19 +70,23 @@ function makeVirtual(): any {
update(part: ChildPart, args: DirectiveParameters<this>) {
this.cont = partToScheduler.get(part);
if (!this.cont || this.cont.renderer !== renderer) {
this.cont = new Scheduler(renderer, part, (r: unknown) => {
this.setValue(r);
});
this.cont = new Scheduler(
renderer as Renderer<T>,
part,
(r: unknown) => {
this.setValue(r);
}
);
partToScheduler.set(part, this.cont);
schedulerToPart.set(this.cont, part);
teardownOnRemove(this.cont, part);
}
this.cont.args = args;
this.cont.update();
return this.render(args);
return this.render(...args);
}

render(args: unknown) {
render(...args: T) {
return noChange;
}
}
Expand All @@ -79,8 +97,8 @@ function makeVirtual(): any {
return virtual;
}

function teardownOnRemove(
cont: BaseScheduler<object, ChildPart, Renderer, ChildPart>,
function teardownOnRemove<T extends unknown[]>(
cont: BaseScheduler<object, ChildPart, Renderer<T>, ChildPart>,
part: ChildPart,
node = part.startNode
): void {
Expand Down

0 comments on commit 4705ede

Please sign in to comment.