How to Get the Type of an Object in PowerShell

To get the type of an object or variable in PowerShell, call its GetType() method. .Name gives the short name and .FullName the full .NET name:

$city = 'Austin'
$city.GetType().Name
$city.GetType().FullName

Output:

String
System.String

To test for a type instead of reading it, use the -is operator, covered below. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1, with the same results.

Common PowerShell types

Here’s what GetType() returns for the values you’ll meet most often:

$values = 'Austin', 42, 3000000000, 19.99, $true, (Get-Date), @(1, 2), @{ State = 'TX' },
          [pscustomobject]@{ Name = 'Alice' }

foreach ($v in $values) {
    '{0,-22} {1}' -f $v.GetType().Name, $v.GetType().FullName
}

Output:

String                 System.String
Int32                  System.Int32
Int64                  System.Int64
Double                 System.Double
Boolean                System.Boolean
DateTime               System.DateTime
Object[]               System.Object[]
Hashtable              System.Collections.Hashtable
PSCustomObject         System.Management.Automation.PSCustomObject
PowerShell GetType Name and FullName for common values
Short and full type names for nine common values (PowerShell 7)

Notice 3000000000: it’s too big for Int32, so PowerShell picks Int64 on its own. A list in parentheses or @() is always Object[], whatever it holds.

Check for $null before calling GetType()

$null has no type, and calling a method on it throws “You cannot call a method on a null-valued expression.” Check first:

$result = $null

if ($null -eq $result) { 'No value, so there is no type to check' }
else { $result.GetType().Name }

Output:

No value, so there is no type to check

Put $null on the left of -eq, as here. Checking for null or empty values explains why.

Get the type with Get-Member

Get-Member shows the type name along with every property and method. Be careful with arrays: piping sends the items one at a time, so you get the types of the items, not the array:

$mixed = 1, 'two', 3

'Piped to Get-Member:'
$mixed | Get-Member | Select-Object -ExpandProperty TypeName -Unique

'With -InputObject:'
(Get-Member -InputObject $mixed).TypeName | Select-Object -Unique

Output:

Piped to Get-Member:
System.Int32
System.String
With -InputObject:
System.Object[]
PowerShell Get-Member on an array vs Get-Member -InputObject
The pipeline describes the items, -InputObject describes the array (Windows PowerShell 5.1)

Use Get-Member -InputObject when you want the container itself. The Get-Member documentation covers -MemberType and other filters.

Check a type with the -is operator

-is returns True or False, which is what you want in an if statement. It checks the actual type, so a ZIP code stored as text isn’t an int:

$zip = '78701'

"Is a string: $($zip -is [string])"
"Is an int:   $($zip -is [int])"
"Is a number after conversion: $(($zip -as [int]) -is [int])"

Output:

Is a string: True
Is an int:   False
Is a number after conversion: True

-as tries a conversion and returns $null if it fails, so it pairs well with -is. Converting a string to an int has more on this. Microsoft covers -is, -isnot and -as in about_Type_Operators.

Check if a variable is an array

-is [array] works for normal PowerShell arrays, but it returns False for ArrayList and generic List collections. Test for IList to catch all of them:

$plain   = 'WEB01', 'WEB02'
$arrList = [System.Collections.ArrayList]@('WEB01', 'WEB02')
$list    = [System.Collections.Generic.List[string]]@('WEB01', 'WEB02')
$text    = 'WEB01'

foreach ($name in 'plain', 'arrList', 'list', 'text') {
    $v = Get-Variable -Name $name -ValueOnly
    '{0,-8} -is [array]: {1,-6} -is [Collections.IList]: {2}' -f $name, ($v -is [array]), ($v -is [System.Collections.IList])
}

Output:

plain    -is [array]: True   -is [Collections.IList]: True
arrList  -is [array]: False  -is [Collections.IList]: True
list     -is [array]: False  -is [Collections.IList]: True
text     -is [array]: False  -is [Collections.IList]: False
PowerShell check if a variable is an array with -is array and IList
Only IList catches ArrayList and List[string] too (PowerShell 7)

A string is not an IList, so the last line correctly says False.

Don’t use .Count or IEnumerable to spot arrays

Both tests you’ll find online give wrong answers. Every value has a Count, and strings are enumerable:

$text  = 'Austin'
$empty = $null

"'Austin'.Count = $($text.Count)"
"`$null.Count    = $($empty.Count)"
"String is IEnumerable: $($text -is [System.Collections.IEnumerable])"

Output:

'Austin'.Count = 1
$null.Count    = 0
String is IEnumerable: True

So $x.Count -gt 1 fails for a one-item array, and IEnumerable lets a string pass. Stick with -is.

One result from a command isn’t an array

When a command returns a single object, you get that object, not a one-item array. Wrap the command in @() to always get an array:

$files = Get-ChildItem -Path C:\psfaqs\OneFile
"Without @(): $($files.GetType().Name), is array: $($files -is [array])"

$files = @(Get-ChildItem -Path C:\psfaqs\OneFile)
"With @():    $($files.GetType().Name), is array: $($files -is [array])"

Output (the folder holds one file):

Without @(): FileInfo, is array: False
With @():    Object[], is array: True

That makes .Count and indexing safe whatever the comman