Skip to content

Conversation

@canadaduane
Copy link
Contributor

@canadaduane canadaduane commented Jan 28, 2025

One of the issues I've seen with the current syntax is the slightly awkward way in which typescript meets DLight. There are ways to make it work, but we see the mismatch in things like as Pretty as Typed and where we assign = required to properties, or in the way in which @children, @content, and @props are sometimes unclear.

This PR is an exploration of alternative syntax ideas. Nothing here is a proposal at this point, just a pastiche of "what if" scenarios.

One of my favorite ideas so far is using Class Expressions instead of static classes. As such, it's possible to pass a Class Expression into a component function that both re-interprets the type and returns a function that instantiates the class--meaning no as Pretty as Typed<> is necessary. (See PR's "Files changed" tab to see the types that make this possible).

From what I understand, Class Expressions do not allow for decorators until Typescript 5, however, so there is a downside in the amount of annotation we can give the transpiler. I've attempted to work around this by making public properties equate with @Props, and private properties equate with local class variables.

We could also use the prop children to pass children in.

const Greet = component(
  class {
    // Public variables would be used as props, replaced by setter-like functions
    times: number;
    name: string;
    prefix?: string;

    // A specially-named `children` public variable would take the place
    // of the `@Children` decorator
    children: DLightNode

    // Private variables would be used as "internal" state
    #greeting = "hi";

    // Constructor params would become the type of the `Greet()` params
    // instead of the `@Content` decorator
    constructor(public links: string[]) {}

    body() {
      this.links.forEach(link => console.log("link:", link);

      for (let i = 0; i < this.times; i++) {
        console.log(
          [this.#greeting, this.prefix, this.name].filter(Boolean).join(" "),
        );
      }
    }
  },
  // Optional list of public methods or properties to omit from the type system
  ["body", "links"],
);

const g = Greet(["hello"]).name("KJ").times(2);
g.body()
// link: hello
// hi KJ
// hi KJ

@codesandbox
Copy link

codesandbox bot commented Jan 28, 2025

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants