Skip to content

Typed commands #1512

Closed
Closed
@zurfyx

Description

I'd like to add to #1412 and #1511 to propose a type-safe approach.

Problem:

Commands are currently heavily error-prone:

  1. You can misspell the type and it will silently never trigger in your app
  2. You can misinterpret the types

Part of this problem is caused by the ability to listen to multiple commands at once.

Proposal

Encourage type safety within Lexical core and user-created commands. Make it so that you can only listen to a specific command at once and
this command is strictly type safe and provided by Lexical core.

execCommand<T>(type: Command<T>, payload: T): void;
registerCommand<T>(type: Command<T>, payload: (T) => void): void;

class Command<T> {
  type: string;
  constructor(type: string) {
    this.type = type;
  }
}
const formatTextCommand = new Command<string>('formatText');
new LexicalEditor().execCommand(formatTextCommand, 'bold');
new LexicalEditor().registerCommand(formatTextCommand, (format) => {
  // bold
});

The generic type above, while seemingly unused, enables us to offer type safety for the payload.

[Optionally] We can do like transforms where we check for the command reference to ensure that we're strictly referring to the same command, in which case we don't even need the type.

class Command<T> {}
const formatTextCommand = new Command<string>();

Trade-offs

(+) It's type safe
(-) It's more costly, we have to provide an instance for every single command
(-) It more verbose, especially for some Lexical core/React. For most internal/real-life usages it should be equivalent though.

Metadata

Labels

enhancementImprovement over existing feature

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions