Búsqueda de sitios web

stimulusjs - Declarar dinámicamente tipos de destino de Stimulus para TypeScript


Estoy escribiendo controladores de stimulus en TypeScript y siento que debe haber una mejor manera de declare todas las propiedades has*Target/*Target/*Targets que declararlas una por una.

¿Alguien sabe si lo que estoy buscando siquiera es posible? Gracias de antemano

Aquí hay un código con el que he estado jugando intentando hacer que funcione

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;
    }
  }
}

EDITAR El compilador dice La clase 'default' implementa incorrectamente la interfaz 'ControllerWithTarget<Targets>'.

Respuesta #1

Aquí hay un ejemplo de cómo lo implementaría:

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;

interface Targets extends Record<typeof targets[number], HTMLElement> {
  button: HTMLButtonElement;
  container: HTMLDivElement;
}

type ControllerWithTarget<T> =
  & Transform.HasTarget<T>
  & Transform.Target<T>
  & Transform.Targets<T>;

export default class extends Controller implements ControllerWithTarget<Targets> {
  static targets = [...targets];

  disableButton(): void {
    if (this.hasButtonTarget) {
      this.buttonTarget.disabled = true;
    }
  }
}

Artículos relacionados