plopjs / plop

Consistency Made Simple
http://plopjs.com
MIT License
7.18k stars 280 forks source link

How to write a Dynamic Actions Array in TypeScript? #448

Open awhitford opened 2 months ago

awhitford commented 2 months ago

I am using plopjs and was having a great time until I decided to migrate to TypeScript (because I like types). What is the advice for using a Dynamic Actions Array like this in TypeScript?

actions: (answers) => {
}

Inside the closure, I want to be able to reference the prompts like: answers.projectName. If I create an interface for the prompt parameters, like:

interface PromptProps {
  projectName: string
}

Then, I can add type information like this:

actions: (answers: PromptProps) => {
}

While this solves the answers.projectName problem, Typescript still complains about the actions declaration:

Type '(answers: PromptProps) => (string | ((answers: PromptProps) => string) | { type: string; path: string; pattern: RegExp; template: string; })[]' is not assignable to type 'Actions | undefined'.
  Type '(answers: PromptProps) => (string | ((answers: PromptProps) => string) | { type: string; path: string; pattern: RegExp; template: string; })[]' is not assignable to type 'DynamicActionsFunction'.
    Types of parameters 'answers' and 'data' are incompatible.
      Type 'Answers | undefined' is not assignable to type 'PromptProps'.
        Type 'undefined' is not assignable to type 'PromptProps'.ts(2322)

What is the solution?

CC: @crutchcorn @cspotcode

amoghkulkarnifr commented 2 weeks ago

I defined a new derived type like so

type ActionsConfig =
  | PlopTypes.ActionConfig
  | PlopTypes.AddActionConfig
  | PlopTypes.AddManyActionConfig
  | PlopTypes.AppendActionConfig
  | PlopTypes.ModifyActionConfig;

and used it in the function similar to what you have done

actions: (data) => {
  var actionsToRun: ActionsConfig[] = [];

  if (data && data.confirm) {
    actionsToRun.push({
      type: 'add',
      path: 'src/helpers/{{kebabCase helper_file_name}}.ts',
      templateFile: 'templates/helper.hbs',
      skipIfExists: true,
    });
  } else {
    console.log('Helper generation aborted');
  }

  return actionsToRun;
}