I'm writing stimulus controllers in TypeScript and I feel like there has to be a better way of declare
ing all of the has*Target
/*Target
/*Targets
properties than declaring each and every one.
Does anyone know if what I'm looking for is even possible? Thanks in advance
Here's some code I've been playing around with trying to get it to work
import { Controller } from '@hotwired/stimulus';
namespace Transform {
export type HasTarget<T> = {
[K in keyof T as `has${Capitalize<string & K>}Target`]: boolean;
};
export type Target<T> = {
[K in keyof T as `${string & K}Target`]: T[K];
};
export type Targets<T> = {
[K in keyof T as `${string & K}Targets`]: Array<T[K]>;
};
}
const targets = [
'button',
'container',
] as const;
type TargetList = typeof targets;
interface Targets extends Record<TargetList[number], HTMLElement> {
button: HTMLButtonElement;
container: HTMLDivElement;
}
type ControllerWithTarget<T> =
& Transform.HasTarget<T>
& Transform.Target<T>
& Transform.Targets<T>;
// Trying to achieve something like this
export default class extends Controller implements ControllerWithTarget<Targets> {
static targets = [...targets];
// declare readonly hasButtonTarget: boolean;
// declare readonly buttonTarget: HTMLButtonElement;
// declare readonly buttonTargets: Array<HTMLButtonElement>;
// declare readonly hasContainerTarget: boolean;
// declare readonly containerTarget: HTMLDivElement;
// declare readonly containerTargets: Array<HTMLDivElement>;
disableButton(): void {
if ( this.hasButtonTarget ) {
this.buttonTarget.disabled = true;
}
}
}
EDIT The compiler says Class 'default' incorrectly implements interface 'ControllerWithTarget<Targets>'.