Skip to content

PowerShell Type Operators

How to use PowerShell's -is, -isnot, and -as operators for safe type checking and conversion without runtime errors, including inheritance validation and graceful handling of invalid data.

Type operators test, validate, and convert the underlying .NET type of values and objects in memory. Because PowerShell is an object-oriented scripting language built on the .NET Common Language Runtime (CLR), variables and pipeline items carry explicit type definitions. Type operators allow you to verify object inheritance without risking null-reference exceptions and safely coerce data without throwing terminating runtime errors.

They provide a safer, more explicit alternative to direct type casting when the outcome of a conversion isn't guaranteed.

The -is and -isnot Operators

The -is and -isnot operators evaluate whether an object is an instance of a specified .NET type, inherits from a particular base class, or implements a specific interface. They always return a boolean: $true or $false.

Syntax

<object> -is [<TypeAccelerator> or <Full.NET.TypeName>]
<object> -isnot [<TypeAccelerator> or <Full.NET.TypeName>]

Basic Type Checking

Consolepowershell
$count = 42
$count -is [int]
$count -is [string]
Outputplaintext
True
False
Consolepowershell
$name = "Tom"
$name -isnot [int]
Outputplaintext
True

where:

  • [int], [string], etc. are type accelerators, the same bracketed shorthand used when declaring strongly-typed variables.
  • -isnot is simply the negated form of -is.
test-types.ps1powershell
$NodePort = 8080
$NodeName = "sql-cluster-01"
$Services = @("wuauserv", "bits")

[PSCustomObject]@{
    IsPortInt       = ($NodePort -is [int])
    IsNameString    = ($NodeName -is [string])
    IsServicesArray = ($Services -is [array])
    PortNotString   = ($NodePort -isnot [string])
}
Consolepowershell
pwsh ./test-types.ps1
Outputplaintext
IsPortInt IsNameString IsServicesArray PortNotString
--------- ------------ --------------- -------------
     True         True            True          True

Inheritance and Interface Verification

Unlike inspecting the string output of .GetType().Name (which only returns the exact leaf class), the -is operator respects .NET type inheritance hierarchies and interfaces:

inheritance-check.ps1powershell
$NumberList = @(1, 2, 3)

[PSCustomObject]@{
    IsArray        = ($NumberList -is [System.Array])
    IsIEnumerable  = ($NumberList -is [System.Collections.IEnumerable])
    IsObject       = ($NumberList -is [System.Object])
    IsSingleNumber = ($NumberList -is [int])
}
Consolepowershell
pwsh ./inheritance-check.ps1
Outputplaintext
IsArray IsIEnumerable IsObject IsSingleNumber
------- ------------- -------- --------------
   True          True     True          False

where:

  • System.Array implements the IEnumerable interface, so -is [System.Collections.IEnumerable] evaluates to $true.
  • In .NET, all reference and value types derive from System.Object, so -is [System.Object] evaluates to $true.

Safe Type Conversion with the -as Operator

In PowerShell, direct type casting using bracket notation (e.g., [int]$val = "abc") throws a terminating exception if the input string or object cannot be converted into the target type.

The -as operator performs a safe type conversion. It attempts to convert the left-hand operand to the specified type:

  • If the conversion succeeds, it returns the newly converted object.
  • If the conversion fails, it returns $null instead of throwing an error or interrupting script execution.

Basic Example

Example 1:

Consolepowershell
$value = "100" -as [int]
$value
$value.GetType().Name
Outputplaintext
100
Int32

Example 2:

Consolepowershell
$invalid = "not-a-number" -as [int]
$invalid
Outputplaintext

where:

  • "100" -as [int] succeeds, producing an actual Int32 value.
  • "not-a-number" -as [int] fails silently, returning $null instead of throwing an error.

Direct Casting vs. Safe Conversion (-as)

Feature Direct Cast ([Type]$val) Safe Conversion ($val -as [Type])
On Successful Conversion Returns converted object Returns converted object
On Conversion Failure Throws terminating exception Returns $null
Script Execution Halts (unless trapped in try/catch) Continues normally
Best Used For Parameter validation, enforcing strict constraints Validating arbitrary user input, CSV parsing, soft type checking
compare-casting.ps1powershell
$RawInput = "19200"
$BadInput = "NotANumber"

$Port = $RawInput -as [int]
$FailedPort = $BadInput -as [int]

[PSCustomObject]@{
    InputParsed   = $RawInput
    ResultValue   = $Port
    UnderlyingType = $Port.GetType().Name
    FailedResult  = if ($null -eq $FailedPort) { "Parsed as `$null" } else { "Success" }
}
Consolepowershell
pwsh ./compare-casting.ps1
Outputplaintext
InputParsed ResultValue UnderlyingType FailedResult
----------- ----------- -------------- ------------
19200             19200 Int32          Parsed as $null

-is vs -as at a Glance

Operator Purpose Returns on Failure
-is Checks whether a value already is a given type $false (never throws)
-isnot Checks whether a value is not a given type $false (never throws)
-as Converts a value to a given type $null (never throws)

Practical Examples

Validating Function Input

validate-type.ps1powershell
function Show-Total {
    param($Value)

    if ($Value -isnot [int] -and $Value -isnot [double]) {
        Write-Warning "Expected a numeric value, got $($Value.GetType().Name)."
        return
    }

    Write-Output "Total: $Value"
}

Show-Total -Value 100
Show-Total -Value "not-a-number"
Consolepowershell
./validate-type.ps1
Outputplaintext
Total: 100
WARNING: Expected a numeric value, got String.

Safe Conversion in a Loop

safe-conversion.ps1powershell
$inputs = @("10", "25", "abc", "40")

foreach ($item in $inputs) {
    $number = $item -as [int]
    if ($null -eq $number) {
        Write-Warning "Skipping invalid value: $item"
        continue
    }
    Write-Output "Valid number: $number"
}
Consolepowershell
./safe-conversion.ps1
Outputplaintext
Valid number: 10
Valid number: 25
WARNING: Skipping invalid value: abc
Valid number: 40

Sanitizing Input Data

The following script accepts raw, unvalidated configuration strings (such as those read from a plain text .ini file or an external API) and uses -as, -is, and conditional branching to validate and cast each entry:

sanitize-configuration.ps1powershell
$RawConfig = @{
    TargetHost   = "web-lb-01"
    ServicePort  = "443"
    MaxLoadRatio = "0.85"
    ScheduledAt  = "2026-01-15 02:00:00"
    RetryCount   = "InvalidInteger"
}

$SanitizedPort = $RawConfig.ServicePort -as [int]
if ($null -eq $SanitizedPort -or $SanitizedPort -lt 1 -or $SanitizedPort -gt 65535) {
    Write-Warning "Invalid port encountered. Reverting to default 80."
    $SanitizedPort = 80
}

$SanitizedRatio = $RawConfig.MaxLoadRatio -as [double]
if ($null -eq $SanitizedRatio) {
    $SanitizedRatio = 0.50
}

$SanitizedDate = $RawConfig.ScheduledAt -as [datetime]

$SanitizedRetries = $RawConfig.RetryCount -as [int]
if ($null -eq $SanitizedRetries) {
    $SanitizedRetries = 3 # Safe default fallback
}

$ValidatedPayload = [PSCustomObject]@{
    HostName     = $RawConfig.TargetHost
    PortNumber   = $SanitizedPort
    LoadLimit    = $SanitizedRatio
    ExecutionTime = $SanitizedDate
    MaxRetries   = $SanitizedRetries
}

$ValidatedPayload | Format-List
Consolepowershell
pwsh ./sanitize-configuration.ps1
Outputplaintext
HostName      : web-lb-01
PortNumber    : 443
LoadLimit     : 0.85
ExecutionTime : 1/15/2026 2:00:00 AM
MaxRetries    : 3

And if you add these lines at the end of the script above to verify that the output object properties are strongly typed:

Consolepowershell
$ValidatedPayload.ExecutionTime -is [datetime]
$ValidatedPayload.PortNumber -is [int]
Outputplaintext
True
True

Best Practices

  • Use -is / -isnot for type checking in conditionals to avoid null-reference exceptions.
  • Use -as for safe conversion when input may be invalid; it returns $null instead of throwing.
  • Prefer -is over .GetType() when the variable might be $null.
  • Always validate the result of -as with a $null check before using the converted value. Remember that -is respects inheritance: an array is also an IEnumerable and an Object.
  • Combine -as with fallback defaults to sanitize external data safely.
Navigation