It's possible in PowerShell to define an output type on scripts. Consider myScript.ps1
:
[OutputType([String])]
param(
[string]$name
)
The following returns String
:
(Get-Command .\myScript.ps1).OutputType.Name
But I would like to specify that a script returns text/json
or text/xml
. What would be a good way of doing that?
Inventing types for OutputType (e.g. [String.JSON]
) does not work.
There are two independent, but complementary mechanisms for declaring output types:
Important: Both ways of declaring output types are informative only and aren't enforced by PowerShell at runtime.
Mechanism A: Using the
OutputType
attribute above theparam()
declaration in a script or function, as in the question:Always use this mechanism, and, if necessary, supplement with mechanism B.
Only recognizes full type names of .NET types or the name of PowerShell type accelerators and no up-front validation is performed, but if an unrecognized type is encountered at invocation time:
'System.Text.Encoding'
): it is quietly ignored.[System.Text.Encoding]
): the function call breaks on invocationThis strict, type-based integration enables tab completion / IntelliSense (command line / Visual Studio Code)
As for when you may want to use mechanism B too:
If the .NET type names don't tell the full story, as in the question.
If a function outputs multiple types and you want to verbally describe what types are output when.
[Supplemental] Mechanism B: Using the
.OUTPUTS
section of comment-based help:Accepts free-form descriptions; while referencing actual type names makes sense, doing so is not enforced.
While you can use this mechanism alone, doing so forgoes the advantages of tab completion and IntelliSense.
Therefore, use it to supplement mechanism A, if needed, but note that:
If both mechanisms are used,
Get-Help
only shows the mechanism B definitions.Since the two mechanisms are independent, you must manually ensure that the free-form information specified is complete and consistent with the mechanism A declarations.
To examine the output-type information with human eyeballs, use
(Get-Help <cmd>).returnvalues
(caveat: requires help to be defined, such as via comment-based help) or read theOUTPUTS
section of the output fromGet-Help -Full <cmd>
.This will either show the free-form
.OUTPUTS
content or, in its absence, the full type names of the[OutputType[]]
-declared types.For programmatic access, use
(Get-Command <cmd>).OutputType
, which returns[System.Management.Automation.PSTypeName]
instances whose.Type
property contains the actual type.Details below, starting with the answer to the original question.
Mechanism A: Using
OutputType
attribute(s) aboveparams()
:You may only specify .NET types as arguments to the
OutputType
attribute, so strings such astext/json
ortext/xml
that reflect MIME types won't work.If you want string output, you've already chosen the closest approximation of your MIME types in terms of .NET types:
[OutputType([String])]
You may specify multiple types in a single
[OutputType()]
attribute, or you may use individual attributes.You must use individual attributes if you want to map output types to specific parameter sets (e.g.,
[OutputType([string], ParameterSetName='NameOnly')]
).As of Windows PowerShell v5.1 / PowerShell Core v6.0.1, however, this information is neither used by tab completion / IntelliSense nor reflected in the output from
Get-Help -Full
.Note: For a type to be recognized by the
OutputType
attribute at invocation time,use either the full type name (e.g.,
[System.Text.RegularExpressions.Match]
rather than just[Match]
) or the name of a PowerShell type accelerator, such as[regex]
.[<fullTypeName>]
at the prompt and see if it is recognized as a type; additionally you may choose between specifying the type as a string (e.g.,'System.Text.Encoding'
) or as a type literal (e.g., (e.g.,[System.Text.Encoding]
), which has behavioral implications - see below.if the specified type isn't present at invocation time, e.g., because the assembly containing the type hasn't been loaded, the behavior depends on how the output was declared:
Beyond that,
either: simply describe the specific types of strings that your cmdlet outputs in its help text, such as via mechanism B described below,
or: create custom .NET types whose names reflect the desired conceptual type, and specify them in the
OutputType
attribute - see below.As stated, despite its constrained nature, the
OutputType
attribute is purely informative at runtime - it is, however, used for tab completion and IntelliSense (Visual Studio Code).Example of using a custom type:
You then get:
Note that the
[System.Management.Automation.PSTypeName]
instances that.OutputType
outputs are not the same as the[type]
instances you get when you inspect a type directly:The
.Name
property of[System.Management.Automation.PSTypeName]
corresponds to the.FullName
property of[type]
, so you get the full type name if the type is recognized (available in the session); otherwise, it is the name as originally specified.Mechanism B: Using the
.OUTPUTS
section in comment-based help:Conceptual help topic
Get-Help about_Comment_Based_Help
describes how section.OUTPUTS
inside comment-based help for scripts and functions can be used to list and describe output types.Note: Similarly, the
.INPUTS
section can be used to describe supported input types, though that is arguably less interesting, given that specifying input types is an integral part of parameter declaration and documentation. By and large,.INPUTS
functions analogously to.OUTPUTS
, with only differences mentioned below.An
.OUTPUTS
section uses the following format suggested by the examples in the help topic, but note that the text is ultimately free-form, and no structure is enforced.Even though the help topic (as of PSv5) doesn't mention it, it seems that in the event of multiple output types, each should be described in its own
.OUTPUTS
section.That said, the free-form format allows you to describe multiple output-type descriptions in a single section.
Example, taking advantage of the free-form format to describe the output in terms of MIME types:
Note that when using
Get-Help
to view the help as a whole, the (aggregated).OUTPUTS
(and.INPUTS
) sections are only shown withGet-Help -Full
.Querying that information programmatically essentially yields the
OUTPUTS
section fromGet-Help -Full
verbatim (with individual.OUTPUTS
sections in the source concatenated with an empty line in between, and extra trailing empty lines):To access the descriptions individually, by index:
However, given the free-form nature of the descriptions and that they're intended for human consumption, this granular access may not be needed.
That said, using this form returns the text without extra whitespace, so
(Get-Help foo).returnvalues.returnvalue.type.name
can be used to return all text without empty lines.This works analogously for the
.INPUTS
sections:(Get-Help foo).inputTypes.inputType.type.name
One neat way is using the PowerShell help comment syntax.
You can access this information from the
Get-Help
object:Results in:
Also works on standard cmdlets:
Returns: