Search code examples
.netpowershellterminology

What do you call these? [array][string][int]


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" }

Solution

  • 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.