OutputType attribute warning in PowerShell with PSScriptAnalyzer
Asked Answered
S

1

5

Below is a sample function which declares OutputType.

I understand this is only for documentation purposes but the problem here is when I invoke PSScriptAnalyzer:

invoke-scriptanalyzer . -IncludeRule PSUseOutputTypeCorrectly

it will tell me this:

The cmdlet 'Test-Function' returns an object of type 'System.Object[]' but this type is not declared in the OutputType attribute.

function Test-Function
{
    [CmdletBinding()]
    [OutputType([System.Management.Automation.PSCustomObject[]])]
    param ()

    [PSCustomObject[]] $TestObject = @()

    for ($i = 0; $i -lt 5; $i++)
    {
        $TestObject += [PSCustomObject]@{
            Key1 = "Value1"
            Key2 = "Value2"
        }
    }

    return $TestObject
}

The question is that I suspect this informational message is false positive but can't confirm.

I think I declared the OutputType attribute just fine, or maybe not?

Why would I need to specify [OutputType([System.Object[]])] as output type? if I'm returning PSCustomObject[]?

Sable answered 29/2, 2020 at 15:54 Comment(1)
There is a GitHub issue open for this. You can go up-vote it at github.com/PowerShell/PSScriptAnalyzer/issues/1471Sesquiplane
N
6

Unless otherwise specified, whatever you return from a function is enumerated by the pipeline, so by the time you assign anything to a variable for example, your [psobject[]] will have been "unpacked" and stuffed back into a dynamically size [object[]].

Use Write-Output -NoEnumerate if you want to return an enumerable collection as-is:

function Test-Function
{
    [CmdletBinding()]
    [OutputType([System.Management.Automation.PSCustomObject[]])]
    param ()

    [PSCustomObject[]] $TestObject = @()

    for ($i = 0; $i -lt 5; $i++)
    {
        $TestObject += [PSCustomObject]@{
            Key1 = "Value1"
            Key2 = "Value2"
        }
    }

    Write-Output $TestObject -NoEnumerate
}
Namedropper answered 29/2, 2020 at 16:3 Comment(3)
I see, that reminds me of about_return just did take a read again, but didn't know it would convert the type from one to another in this case. learn.microsoft.com/en-us/powershell/module/…Sable
Indeed; the alternative that is more concise and efficient - but also more obscure - is to wrap the output collection in an aux. single-element array: , $TestObject (with or without preceding it with return). @metablaster, while it is in effect a conversion, what happens is that the [pscustomobject] instances travel one by one through the pipeline, and only on capturing the overall output (e.g., with $var = ... or as part of an expression, (...)) does PowerShell collect multiple output objects in an [object[]] array - whatever their type is.Oldfangled
There is a GitHub issue open for this. You can go up-vote it at github.com/PowerShell/PSScriptAnalyzer/issues/1471Sesquiplane

© 2022 - 2024 — McMap. All rights reserved.