-
Notifications
You must be signed in to change notification settings - Fork 443
Dynamically declare *Target properties with TS #723
Description
I've looked over #121 and #466 and while they are similar, they aren't quite what I'm looking for. I know when using TS I need to declare the *Target properties I want to use. I'm fine with that but I'm wondering if that can done dynamically.
declareing all of the properties isn't too bad when there's only 1 or 2 targets, but sometimes I have numerous targets and would like to avoid declareing every one of them when they're all very similar. It's a similar situation for values and outlets but I use those far less than targets
Is there a way to dynamically declare these properties or to tell TS that Controller does correctly implement ControllerWithTarget<Targets> below (while avoiding @ts-ignore and similar) ?
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;
}
}
}Any help is greatly appreciated, thanks!