PowerShell OutputType attribute not working

1.8k views Asked by At

The OutputType attribute is supposed to give type information through intellisense. However it does not work as expected.

I have tested this in both PSReadline and PowerShell ISE and they work the same.

The following is a sample function I am using:

Function Get-FirstChar
{
    [OutputType([String])]
    [CmdletBinding()]

    param(
      [Parameter(Mandatory=$true, ValueFromPipeline=$true)][string[]]$Strings
    )

    process {
        foreach ($str in $Strings) {
            $str.SubString(0, 1);
        }   
    }
}

When I do:


"John","Simon" | Get-FirstChar | % { $_.<TAB> }

I get the suggestions (regardless of platform):

Equals       GetHashCode  GetType      ToString

However when I do:

("John","Simon" | Get-FirstChar).<TAB>

Then I get all the string methods like SubString etc.

I have also tried a string array String[] as the output type and it still don't work :(

Can someone shed like on how to use OutputType attribute to say that one or more strings will be returned from a powershell function?

Thank you

1

There are 1 answers

4
BartekB On BEST ANSWER

Obviously, your expectations are correct. I must say I'm surprised it doesn't work for [string] as it does work for other, complex types:

function Get-ProcessEx {
    [OutputType([System.Diagnostics.Process])]
    param ()
}

Get-ProcessEx | ForEach-Object { $_.}

When I've tried with [string] I get only property (and that is not very helpful for strings, the only property they have is Length). I would consider that a bug, or limitation of the way tools like PowerShell ISE and PSReadline respond to information that objects returned from your functions are strings. E.g. if you try the same with other simple types, result matches the expectations:

function Get-Int {
    [OutputType([int])]
    param ()
}

Get-Int | ForEach-Object { $_. }

It seems to be affecting cmdlets too, I can't get any of existing cmdlets that define same OutputType to provide tab-completion for string's methods:

Get-Command | Where-Object { $_.OutputType.Type -eq [String] }
# Join-Path, not too surprisingly, returns System.String...
Join-Path -Path C:\temp -ChildPath a.txt | ForEach-Object { $_.}

I guess in either case it's worth reporting on PowerShell's UserVoice.