Repository: gatsbyjs/gatsby
File: packages/create-gatsby/src/index.ts (TypeScript)

Code before:
    choices: makeChoices(cmses),
  },
  {
    type: `select`,
    name: `styling`,
    message: `Would you like to install a styling system?`,
    hint: `Use arrow keys to move, and enter to select`,
    choices: makeChoices(styles),
  },
  {
    type: `multiselect`,
    name: `features`,
    message: `Would you like to install additional features with other plugins?`,
    hint: `Use arrow keys to move, spacebar to select, and enter to confirm your choices`,
    choices: makeChoices(features),
  },
]

const supportedOptionTypes = [`string`, `boolean`, `number`]

const makePluginConfigQuestions = (
  selectedPlugins: Array<string>
): Array<any> => {
  const formPrompts = selectedPlugins.map((pluginName: string) => {
    const schema = pluginSchemas[pluginName]
    const { keys: options } = schema
    const choices = Object.keys(schema?.keys).reduce((result, name) => {
      const option = options[name]

      if (option?.flags?.presence === `required`) {
        result.push({
          name,
          initial:
            option.flags?.default &&
            supportedOptionTypes.includes(typeof option.flags?.default)
              ? option.flags?.default.toString()
              : undefined,
          message: name,
        })
      }
      return result
    }, [])

    return {
      type: `form`,
      name: `config-${pluginName}`,
      multiple: true,
      message: `Configure required fields for ${pluginName}:`,
      choices,
    }
  })

Review comment (suggestion):
The plugins aren't all objects, and don't all have a `keys` prop, so we should check for this at runtime. This will also narrow the type for TypeScript.
```suggestion
    if (typeof schema === `string` || !(`keys` in schema)) {
      return []
    }
    const { keys: options } = schema
```

Code after:
    hint: `Use arrow keys to move, and enter to select`,
    choices: makeChoices(cmses),
  },
  {
    type: `select`,
    name: `styling`,
    message: `Would you like to install a styling system?`,
    hint: `Use arrow keys to move, and enter to select`,
    choices: makeChoices(styles),
  },
  {
    type: `multiselect`,
    name: `features`,
    message: `Would you like to install additional features with other plugins?`,
    hint: `Use arrow keys to move, spacebar to select, and enter to confirm your choices`,
    choices: makeChoices(features),
  },
]

const supportedOptionTypes = [`string`, `boolean`, `number`]

type PluginName = keyof typeof pluginSchemas
type Schema = Joi.Description & {
  // Limitation in Joi typings
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  flags?: Record<string, any>
}

const makePluginConfigQuestions = (
  selectedPlugins: Array<PluginName>
): Array<any> => {
  const formPrompts = selectedPlugins.map((pluginName: PluginName) => {
    const schema = pluginSchemas[pluginName]
    if (typeof schema === `string` || !(`keys` in schema)) {
      return []
    }
    const options: Record<string, Schema> | undefined = schema?.keys
    const choices: Array<{
      name: string
      initial: string
      message: string
    }> = []

    Object.entries(options).forEach(([name, option]) => {
      if (option?.flags?.presence !== `required`) {
        return
      }
      choices.push({
        name,
        initial:
          option.flags?.default &&