I'm looking for a way to make a cmdlet which receives parameter and while typing, it prompts suggestions for completion from a predefined array of options.
I was trying something like this:
$vf = @('Veg', 'Fruit')
function Test-ArgumentCompleter {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateSet($vf)]
$Arg
)
}
The expected result should be:
When writing 'Test-ArgumentCompleter F', after clicking the tub button, the F autocompleted to Fruit.


PowerShell generally requires that attribute properties be literals (e.g.,
'Veg') or constants (e.g.,$true).Dynamic functionality requires use of a script block (itself specified as a literal,
{ ... }) or, in specific cases, a type literal.However, the
[ValidateSet()]attribute only accepts an array of string(ified-on-demand) literals or - in PowerShell (Core) v6 and above - a type literal (see below).Update:
If you're using PowerShell (Core) v6+, there's a simpler solution based on defining a custom
classthat implements theSystem.Management.Automation.IValidateSetValuesGeneratorinterface - see the 2nd solution in iRon's helpful answer.Even in Windows PowerShell a simpler solution is possible if your validation values can be defined as an
enumtype - see Mathias R. Jessen's helpful answer.Caveat:
*.ps1file) that is invoked directly, i.e. a script that starts with aparam(...)block.classandenumdefinitions referenced in that block would need to be loaded before the script is invoked.using moduleis attempted, which too doesn't work, up to at least PowerShell v7.3.x).param(...)block.To get the desired functionality based on a non-literal array of values, you need to combine two other attributes:
[ArgumentCompleter()]for dynamic tab-completion.[ValidateScript()]for ensuring on command submission that the argument is indeed a value from the array, using a script block.