Powershell: Feature Request: -Is operator: suppress "Cannot convert"error

Created on 9 Sep 2019  路  13Comments  路  Source: PowerShell/PowerShell

Suppress the error on the -is operator when the type is supplied as a string:

$a -is 'UndefinedType'

Cannot convert the "UndefinedType" value of type "System.String" to type "System.Type".
At line:1 char:1
+ $a -is 'UndefinedType'
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException

If "strict" programming is required, the system.type (square brackets) should be used instead:

$a -is [UndefinedType]

Unable to find type [UndefinedType].
At line:1 char:8
+ $a -is [UndefinedType]
+        ~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (UndefinedType:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound

(Were the error is actually generated by the type casting and not the -isoperator.)/sub>

This would allow for easier type checking on types that might not exist in certain environments (like [semver] that doesn't exist in Windows PowerShell, see also: Stackoverflow: How to test a (possible) unknown type?

Besides, I think this is more in line with the general PowerShell behavor set by the PowerShell team: "Type Conversion in PowerShell is, without question, one of the most useful ingredients in its "Magic Sauce" of administrator effectiveness." and looking to other comparison operators, there aren't many operators that can produce an error.

In other words, from my perspective:
$a -is 'UndefinedType' should just return $False without error and $a -isnot 'UndefinedType' should just return $True without error.

Issue-Enhancement Resolution-Answered

Most helpful comment

@iRon7 Even in non-strict mode, PowerShell tries to error on impossible behaviour. For example

[int] "abc"

is an error (unlike say Javascript). Likewise 123 + "abc" is an error. $x.nosuchmethod() is an error. 123/0 is an error. [type] 'nosuchtype' is an error. As much as possible, we try to treat things that make no sense as errors. In particular, we wanted implicit (or explicit) type conversions to be rational so [int] "123" works but [int] "abc".

@SeeminglyScience

I think this would mostly end up just making typos harder to find.

Agree 100%. Type names tend to be long so it's easy to make a mistake.

All 13 comments

Yeah, I think I can get behind this. Asking whether an object is of a nonexistent type should probably just return $false; it certainly still answers the query the operator is designed to address.

FWIW, you can workaround this for the time being with a pattern like this:

$Type = 'UnknownType' -as [type]
$Result = $Type -and $object -is $Type

Which isn't _ideal_ but it does avoid the issue in the meantime. 馃檪

@iRon7 What scenario do you have that ignoring this error would facillitate? In general, hiding errors is bad practice. If you mistype a type name or don't have an assembly loaded you should get an error. If you just want to see if a string names a type then do that i.e.:

PS[1] (83) > "adsasdas" -is [type]
False

I don't think that works the way you claim, @BrucePay? It would be very odd to have two variant behaviours for $string -is [type]

@vexx32 Oops - you're right. My bad. I've been using LanguagePrimitives.ConvertTo in C# a lot lately which does do the conversion

[System.Management.Automation.LanguagePrimitives]::ConvertTo("int32", [type]) != $null

Still, this is pretty straight forward:

PS1> "int32" -as [type] -ne $null
True
PS1> "notatype" -as [type] -ne $null
False

Either way, it doesn't change the fact that silently ignoring errors is bad practice.

Mmm. Depends what you're trying to determine, really.

I'd think the point of -is is simply to determine whether the item in question is an instance of the type given -- not necessarily to also determine whether the given type is actually present in the current session. One task at a time, as it were. :slightly_smiling_face:

I think this would mostly end up just making typos harder to find. Granted that's generally speaking pretty on brand for PowerShell, but the use cases here are not as compelling as with other instances.

Most of the time when you're not using a default type, you're going to be explicitly loading the assembly. In most of the cases you aren't doing that, you probably still need it loaded . In the few cases were you truly want this failure to be ignored, you're better off being slightly more explicit with something like this:

if ('SomeType' -as [type] -and $var -is [SomeType]) {
    return $true
}

@BrucePay, there are pro's and con's with regards a strict programming language but as far I can tell, PowerShell not a strict language (_by default_).
In other words, I do not get an error with the following statements either:

$UndefinedVariable -eq 0
$TypoInVaraible -eq 0

Knowing that there is no technical difference between the above statements, from a developer standpoint it will be preferred to get an error for the later "$TypoInVaraible" example but for the first example, it might be desired in a syntax like:

If ($a -eq 'Varaible') {$a = 'Variable'}

(Knowing that I will not get an error when $a is undefined or $Null)
The same behavior I would expect for the -is operator:

If ($v -is 'semver') {'Patch version: ' + $v.Patch} Else {'No patch version available'}

But this generates an error in Windows PowerShell (I understand that this request will not fix this for this specific -past- example but future versions and environments might cause similar situations)

Btw, the Set-StrictMode should play a roll in this. In strict mode, I actually do expect an error if the type doesn't exist in the current environment or a simple enforcement of the use of a [Type] type (the use of square brackets).

(Once again, a strict syntax can also still be enforced by using square brackets: $v -is [semver])

I would be inclined to also agree that unless Strict Mode is enabled, the proposed behaviour makes sense.

@iRon7 Even in non-strict mode, PowerShell tries to error on impossible behaviour. For example

[int] "abc"

is an error (unlike say Javascript). Likewise 123 + "abc" is an error. $x.nosuchmethod() is an error. 123/0 is an error. [type] 'nosuchtype' is an error. As much as possible, we try to treat things that make no sense as errors. In particular, we wanted implicit (or explicit) type conversions to be rational so [int] "123" works but [int] "abc".

@SeeminglyScience

I think this would mostly end up just making typos harder to find.

Agree 100%. Type names tend to be long so it's easy to make a mistake.

This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.

@iSazonov, what exactly does this automatic close mean? That the request is rejected? Do I need to spam you daily to keep it open until it is accepted or not? (I don't think that is good for housekeeping either.)

That the request is rejected?

@iRon7 The issue is not _locked_ - anybody can comment and share new thoughts.

Main concern here that the enhancement will hide typos. PowerShell is not only programming language where the change would be good but interactive shell where hiding typos is very bad. The discussion shows that interactive scenario is more important and in scripts we can use strong syntax and/or simple workarounds if needed.
We could request Script Analyzer to recommend strong syntax. It is another argument that current compromise is good.

@iSazonov , thanks for the explanation, I can only summarize my arguments:

  • PowerShell is a not a strict language (by default)
  • Other operators like -eq act the same, meaning by default (Set-StrictMode Off) they do not resolve typos
  • Casting typos are not related (an explicit syntax like $v -is [semver] will still produce an error when [semver] is misspelled)
  • Set-StrictMode in this request should enforce strict typing for $v -is 'semver' (e.g. to use: $v -is [semver]) similar to other operators.

Unless something new comes up, I will leave it as it is.

Was this page helpful?
0 / 5 - 0 ratings