How to specify a custom class as the data type for a PowerShell script parameter?

THEOBALD K 20 Reputation points
2025-01-09T17:49:25.4866667+00:00

In Powershell (specifically 5.1), I have a custom class Foo, defined in a file (Foo.ps1 or Foo.psm1) like this:

Class Foo {

....

}

And in a script (.ps1 file) I want to use this type for one of the parameters, e.g.:

Param(

[Foo] $Bar

...

I would like to do it this way because the class definition has constructors for various types. So, for instance, I could call my script with

& myscript.ps1 -Bar 5

and that will call the integer constructor, that turns the int 5 into a Foo. Or, if the value to -Bar is ALREADY a Foo then of course nothing happens.

But I have a chicken-and-egg problem, because in the script, Param() MUST come first. But then, how does it know what a Foo is, since if I try loading the definition first, then Param() won't be recognized. If I load the class definition AFTER, well, PS doesn't work with such forward references. EXCEPT for #requires... BUT #requires DOESN'T import classes.

The best I've figured out so far is this:

Param(

[Object] $Bar

)

. Foo.ps1 # MUST be .ps1 because can't dot-load a .psm1...

$Bar = $Bar -as [Foo]

...

This is a bit klunky, especially if there are multiple parameters with custom classes. And Get-Help then says parameter Bar is an Object, not a Foo. So I need to add extra notes to the comment-based help.

Just wondering if there's a cleaner way.

PowerShell
PowerShell
A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
2,758 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Rich Matheisen 47,581 Reputation points
    2025-01-09T19:48:43.3333333+00:00

    "Param" must come first within a function.

    I think all you'd need to do was to package the script so that the code in your "myscript.ps1" file becomes a function (with a meaningful name) inside a PS1 file. The class(es) can then appear after the script file's "param" set and before the function(s).

    This just a cobbled together example:

    Param($something)
    
    class Foo {
        [int]$int
        [double]$dou
        [string]$str
        Foo([int]$p){
            $this.int = $p
        }
        Foo([double]$p){
            $this.dou = $p
        }
        Foo([string]$p){
            $this.str = $p
        }
    }
    
    # the code that does the work
    Function MyStuff{
        param(
            [Foo]$Bar
        )
        $Bar
    }
    
    # driver
    MyStuff $something
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.