5

What are these called? When scripting in powershell I can use them to set or convert the data type of my variable, but what is the term for this? Is there an official doc for these?

Example:

$var = @("hello","world")
If ($var -is [array]) { write-host "$var is an array" }
mklement0
  • 382,024
  • 64
  • 607
  • 775
arealhobo
  • 447
  • 1
  • 6
  • 17
  • 1
    They’re basically references to dotnet Types - e.g. ```[string].GetType().Name``` returns ```RuntimeType```. – mclayton Apr 07 '21 at 23:13
  • Kind of a trick question since Powershell handles it for you in regards to what it becomes. No need to cast a data type to it, posh knows. Such as `$Var = 2` will be a data type of int. Same with `$Var = "string"`, will be a data type of `[string]`. – Abraham Zinala Apr 07 '21 at 23:46

2 Answers2

6

Don Cruickshank's helpful answer provides one piece of the puzzle, but let me try give a comprehensive overview:

By itself, a [<fullTypeNameOrTypeAccelerator>] expression is a type literal, i.e. a reference to a .NET type in the form of a System.Reflection.TypeInfo instance, which is rich source of reflection on the type it represents.

<fullTypeNameOrTypeAccelerator> can be the full name of a .NET type (e.g., [System.Text.RegularExpressions.Regex] - optionally with the System. prefix omitted ([Text.RegularExpressions.Regex]) or the name of a PowerShell type accelerator (e.g, [regex])


Type literals by themselves are used:

  • Typically, to access static members (typically methods) via ::, the static member-access operator; e.g.:

    # Call the static 'Match' method of the [regex]
    # (System.Text.RegularExpressions.Regex) type.
    # -> '10'
    [regex]::Match('A10', '\d+').Value
    
  • Less frequently, to reflect on the given type by calling the instance methods of the TypeInfo instance that every type literal is; e.g.:

    # Get the names of all .NET interfaces that the [regex]
    # (System.Text.RegularExpressions.Regex) implements.
    # -> 'ISerializable'
    [regex].GetInterfaces().Name
    

Type literals are also used in the following constructs:

  • As casts, to convert (coerce) the (RHS[1]) operand to the specified type or to construct an instance, if possible:

    # Convert a string to [datetime] (System.DateTime).
    # Equivalent to the following call:
    #    [datetime]::Parse('1970-01-01', [cultureinfo]::InvariantCulture)
    [datetime] '1970-01-01'
    
    # Construct a [regex] instance.
    # The same as the following constructor call:
    #     [regex]::new('\d+')
    $re = [regex] '\d+'
    
    • The examples show that PowerShell casts are much more flexible than in C#, for instance, and instance construction and type conversions frequently happen implicitly - see this answer for more information. The same rules apply to all the other uses listed below.
  • As type constraints:

    • To specify the type of a parameter variable in a function or script:

      function foo { param([datetime] $d) $d.Year }; foo '1970-01-01'
      
    • To lock in the type of a regular variable for all future assignments:[2]

      [datetime] $foo = '1970-01-01'
      # ...
      $foo = '2021-01-01' # the string is now implicitly forced to [datetime] 
      
  • As the RHS of the -is and -as operators, for type tests and conditional conversions:

    • -is tests not only for the exact type, but also for derived types as well as interface implementations:

      # Exact type match (the `Get-Date` cmdlet outputs instances of [datetime])
      (Get-Date) -is [datetime]  # $true
      
      # Match via a *derived* type:
      # `Get-Item /` outputs an instance of type [System.IO.DirectoryInfo],
      # which derives from [System.IO.FileSystemInfo]
      (Get-Item /) -is [System.IO.FileSystemInfo] # $true
      
      # Match via an *interface* implementation:
      # Arrays implement the [System.Collections.IEnumerable] interface.
      1..3 -is [System.Collections.IEnumerable] # true
      
    • -as converts the LHS instance to an instance of the RHS type if possible, and returns $null otherwise:

      '42' -as [int] # 42
      
      'foo' -as [int] # $null
      
  • [PowerShell v7.3+ only] As the type arguments in generic method calls:


[1] In the context of operators and mathematical equations, the initialisms LHS and RHS are commonly used, referring to the left-hand side and right-hand side operands, respectively.

[2] Technically, there is no real difference between a parameter and a regular variable: the type constraints functions the same way in both cases, but parameter variables, after having been bound (assigned to) automatically on invocation, aren't usually assigned to again.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Great answer, as usual! If I may, I wanna add a good article to understand a bit more on the subject https://blog.kotlin-academy.com/programmer-dictionary-class-vs-type-vs-object-e6d1f74d1e2e and of course the System Namespace from MS Docs https://learn.microsoft.com/en-us/dotnet/api/system?view=net-5.0 – Santiago Squarzon Apr 08 '21 at 02:40
  • What is RHS? So, *"under the hood"* for powershell cmdlets, do actual .Net types lie? Such as the ones you referenced for exact match like: `Get-Date` is actually just `[DateTime]`, but in Powershell syntax? Still just confused on when I get the data type back from piping a cmdlet to a `Get-Member`, is it just grabbing those objects that lie in those types, or is it the actual type itself? -pardon me if this doesn't make sense – Abraham Zinala Apr 08 '21 at 02:41
  • 1
    @AbrahamZinala, re LHS and RHS: please see the footnote I've just added. I'm not sure I understand your other question: `Get-Date` is a _cmdlet_ that _outputs_ instances of `[datetime]`. You pipe _instances_ to `Get-Member`, which then tells you about their _type_. – mklement0 Apr 08 '21 at 02:47
  • 1
    `Get-Date` is just the way PowerShell has to access the `DateTime Struct` in System Namespace. Almost everything (or everything not sure, cmdlets, data structures, classes, types, etc), that is native to PS is from C# / .NET Framework / .NET Core. mklement0 probably can give us a more accurate answer here. But in some sense, yes, `Get-Date` is accessing the `System.DateTime` and helping you manipulate it @AbrahamZinala – Santiago Squarzon Apr 08 '21 at 03:02
  • 1
    You're welcome, @AbrahamZinala; let me try to phrase it a bit differently: In the expression `(Get-Date) -is [datetime]`, `(Get-Date)` is a _call_ to the `Get-Date` _cmdlet_ and whatever that cmdlet outputs - which happens to be a `[datetime]` instance - becomes the LHS of the `-is` operator. Yes, all objects in PowerShell are instance of .NET types. – mklement0 Apr 08 '21 at 03:18
4

It is called the cast operator. The official documentation uses this term in about_operators.

Cast operator [ ]

Converts or limits objects to the specified type. If the objects cannot be converted, PowerShell generates an error.

Don Cruickshank
  • 5,641
  • 6
  • 48
  • 48