Skip to main content
    Courses/PowerShell/Variables and Data Types

    Lesson 2 • Beginner

    Variables and Data Types

    By the end of this lesson you'll be able to store text, numbers, true/false values, arrays, and hashtables in PowerShell variables, convert between types with casting, and build clean output with string interpolation and here-strings — the foundation of every script you'll write.

    What You'll Learn

    • Create variables with the $ prefix and read their value back
    • Recognise the common types: String, Int32, Double, Boolean and $null
    • Build arrays with @() and hashtables with @{ } and read items from them
    • Convert between types with casts like [int] and [double]
    • Interpolate variables in "double quotes" vs keep text literal in 'single quotes'
    • Write multi-line text cleanly with here-strings

    1. Declaring Variables & Common Types

    To make a variable, pick a name starting with $ and assign a value with =: $name = "Alice". You never declare the type — PowerShell is dynamically typed, so it figures the type out from the value. The everyday types are String (text), Int32 (whole numbers), Double (decimals) and Boolean ($true / $false). There's also $null, which means "no value at all". Read this worked example, run it, then you'll write your own.

    Worked example: variables and their types
    # A variable is a named box that holds a value. In PowerShell every
    # variable name starts with a $ sign — the $ is part of the name.
    $name    = "Alice"        # text  -> String  (use quotes)
    $age     = 30             # whole number -> Int32
    $price   = 19.99          # decimal number -> Double
    $isAdmin = $true          # true/false -> Boolean ($true or $false)
    $nothing = $null          # "no value at all" -> Null
    
    # Every value is a .NET object, so you can ask it for its type name.
    Write-Output "name  is a $($name.GetType().Name)"
    Write-Output "age   is an $($age.GetType().Name)"
    Write-Output "price is a $($price.GetType().Name)"
    Write-Output "admin is a $($isAdmin.GetType().Name)"
    
    # $null is genuinely empty. Comparing to it is how you test "is it set?".
    Write-Output "nothing is null: $($null -eq $nothing)"
    Output
    name  is a String
    age   is an Int32
    price is a Double
    admin is a Boolean
    nothing is null: True
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    2. Strings: Interpolation, Quotes & Here-Strings

    The quote you choose changes what happens. Double quotes expand — a $variable inside the text is replaced by its value, and $(...) runs a small expression and drops the result in. Single quotes are literal — what you type is exactly what you get, so '$name' stays as the text $name. For multi-line text, a here-string (@" ... "@) keeps your layout intact, and the double-quoted form still expands variables inside it.

    Worked example: double vs single quotes and here-strings
    $user = "Sam"
    $count = 3
    
    # Double quotes EXPAND: variables and $(...) subexpressions are replaced.
    Write-Output "Hello, $user!"              # Hello, Sam!
    Write-Output "You have $count messages"   # You have 3 messages
    Write-Output "2 + 2 = $(2 + 2)"           # 2 + 2 = 4   (subexpression)
    
    # Single quotes are LITERAL: nothing is expanded, what you see is what you get.
    Write-Output 'Raw text: $user is not expanded'   # Raw text: $user is not expanded
    
    # A here-string holds multi-line text exactly as written.
    # Double-quoted @" ... "@ still expands variables inside it.
    $report = @"
    User:     $user
    Messages: $count
    Status:   OK
    "@
    Write-Output $report
    Output
    Hello, Sam!
    You have 3 messages
    2 + 2 = 4
    Raw text: $user is not expanded
    User:     Sam
    Messages: 3
    Status:   OK
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    Your turn. The script below is almost complete — fill in the three blanks marked ___ using the hints in the comments, then run it.

    🎯 YOUR TURN: declare three variables and interpolate them
    # 🎯 YOUR TURN — replace each ___ then run the script.
    
    # 1) Make a string called $city set to a city name
    $city = ___          # 👉 text in "double quotes", e.g. "London"
    
    # 2) Make an int called $year set to the current year
    $year = ___          # 👉 a whole number, e.g. 2026
    
    # 3) Make a bool called $isOpen set to true
    $isOpen = ___        # 👉 use $true (not "true")
    
    # These already work once your variables exist (note: double quotes expand):
    Write-Output "In $year, the office in $city is open: $isOpen"
    
    # ✅ Expected output (example):
    #    In 2026, the office in London is open: True
    Output
    In 2026, the office in London is open: True
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    3. Collections: Arrays & Hashtables

    When you need more than one value, reach for a collection. An array holds values in order — build it with @(...) and read items by position, where [0] is the first and [-1] is the last. A hashtable holds key = value pairs (a lookup table) — build it with @{ ... } and read a value by its key with $h.Key or $h['Key']. Inside a string, wrap property access in $(...) so it's evaluated.

    Worked example: arrays with @() and hashtables with @{ }
    # Arrays hold many values in order. Build one with @( ).
    $fruits = @("Apple", "Banana", "Cherry")
    Write-Output "First: $($fruits[0])"       # index 0 is the first item
    Write-Output "Last:  $($fruits[-1])"      # -1 counts from the end
    Write-Output "Count: $($fruits.Count)"    # how many items
    
    # += appends — but it builds a brand-new array each time (slow in big loops).
    $fruits += "Date"
    Write-Output "Joined: $($fruits -join ', ')"
    
    # Hashtables hold key -> value pairs (a lookup table). Build one with @{ }.
    $server = @{
        Name   = "WebServer01"
        IP     = "192.168.1.10"
        Status = "Running"
    }
    Write-Output "Name: $($server.Name)"      # dot access by key
    Write-Output "IP:   $($server['IP'])"     # or bracket access by key
    Output
    First: Apple
    Last:  Cherry
    Count: 3
    Joined: Apple, Banana, Cherry, Date
    Name: WebServer01
    IP:   192.168.1.10
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    4. Type Casting

    Sometimes a value is the wrong type — most often you have text that needs to be a number. Put the target type in square brackets in front of the value to cast it: [int]$typed, [double]$priceText, [string]$age. This matters because PowerShell decides what + does from the left-hand value: a string on the left glues text together, while a number on the left adds. Cast first and the maths behaves.

    Worked example: casting text to numbers with [int] and [double]
    # Text typed by a user is always a String — even if it looks like a number.
    $typed = "42"
    Write-Output "Without casting: $($typed + 8)"   # "428" — string glued together!
    
    # Cast with [int] to force a real number, then maths works.
    $number = [int]$typed
    Write-Output "With [int] cast: $($number + 8)"  # 50
    
    # Cast the other way too: [string], [double], [bool] all work.
    $rounded = [int]3.9        # 4  -> [int] ROUNDS to nearest, it does NOT truncate
    Write-Output "[int]3.9 = $rounded"
    # Surprise: exact .5 ties round to the EVEN number (banker's rounding).
    Write-Output "[int]2.5 = $([int]2.5)"   # 2  (not 3!)
    
    # You can pin a variable's type by casting on the left-hand side.
    [int]$score = "100"
    Write-Output "score is now a $($score.GetType().Name) = $score"
    Output
    Without casting: 428
    With [int] cast: 50
    [int]3.9 = 4
    [int]2.5 = 2
    score is now a Int32 = 100
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    Now you try. Input from a user always arrives as text, so before you can do maths you must cast it. Fill in the two blanks:

    🎯 YOUR TURN: cast text to numbers, then calculate
    # 🎯 YOUR TURN — input always arrives as TEXT, so cast before doing maths.
    $quantityText = "3"
    $priceText    = "4.50"
    
    # 1) Cast $quantityText to a whole number
    $quantity = ___          # 👉 use [int]$quantityText
    
    # 2) Cast $priceText to a decimal number
    $unitPrice = ___         # 👉 use [double]$priceText
    
    $total = $quantity * $unitPrice
    Write-Output "$quantity items at $unitPrice each, total $total"
    
    # ✅ Expected output:
    #    3 items at 4.5 each, total 13.5
    Output
    3 items at 4.5 each, total 13.5
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    Pro Tip

    For large collections that grow in a loop, avoid $arr += item — it copies the whole array every time, which is O(n). Use a typed list instead: $list = [System.Collections.Generic.List[string]]::new() and $list.Add("x"), which is O(1). For ordered key/value data where insertion order matters, use [ordered]@{ ... } — a plain hashtable does not guarantee order.

    Common Errors (and the fix)

    • Single quotes when you wanted interpolation: 'User: $name' prints the literal text $name. Switch to double quotes — "User: $name" — for the value to appear.
    • Property access not expanding in a string: "$server.Name" prints the whole object then the literal .Name. Wrap it in a subexpression: "$($server.Name)".
    • Adding text instead of numbers: "5" + 3 gives 53, not 8, because the left value is a string. Cast first: [int]"5" + 38.
    • Backwards null test: writing $x -eq $null can misbehave when $x is an array. Always put $null on the left: $null -eq $x.
    • Cannot convert value to type "System.Int32": you cast something that isn't a number, e.g. [int]"abc". Make sure the text is numeric before casting.

    📋 Quick Reference

    TaskSyntaxResult
    String$name = "Alice"Alice
    Integer$count = 4242
    Boolean$ok = $trueTrue
    Array$a = @(1,2,3)1 2 3
    Hashtable$h = @{A=1}$h.A → 1
    Interpolate"Hi $name"Hi Alice
    Subexpression"$($h.A + 1)"2
    Cast to int[int]"42"42
    Null test$null -eq $xTrue / False

    Frequently Asked Questions

    Q: Why does my variable print as literal $name instead of the value?

    You wrapped the text in single quotes. Single-quoted strings are literal in PowerShell — nothing inside them is expanded. Use double quotes ("Hello $name") whenever you want a variable's value substituted in.

    Q: How do I put an object's property inside a string, like $server.Name?

    Wrap it in a subexpression: $(...). Inside double quotes, "$server.Name" prints the whole object followed by the literal .Name, because PowerShell only expands the bare variable. Write "$($server.Name)" so the .Name part is evaluated first.

    Q: Why did $typed + 8 give me 428 instead of 50?

    $typed held the string "42", and with a string on the left the + operator concatenates, gluing "8" on the end. Cast it to a number first: [int]$typed + 8 gives 50. This automatic-coercion-by-left-operand surprise is the classic PowerShell trap.

    Q: What's the difference between $null, "" and 0?

    $null means 'no value assigned at all'. An empty string "" is a real String of length 0, and 0 is a real number. They are different things — test for unset with the idiom $null -eq $yourVar (put $null on the left).

    Q: When should I use a here-string instead of normal quotes?

    Reach for a here-string (@" ... "@ or @' ... '@) when your text spans multiple lines or contains lots of quotes you'd otherwise have to escape — banners, config blocks, SQL, HTML. The double-quoted form still expands variables; the single-quoted form keeps everything literal.

    Mini-Challenge: Server Status Report

    No blanks this time — just a brief and an outline to keep you on track. Build it, run it, and check your output against the example in the comments. This combines a hashtable, an array, casting a bool, and a here-string — exactly the kind of small script real automation is made of.

    🎯 Mini-Challenge: build a server status report
    # 🎯 MINI-CHALLENGE: Server status report
    # 1. Make a hashtable $server with keys: Name, IP, and Online (a bool).
    # 2. Make an array $services with 3 service names, e.g. "DNS","Web","SQL".
    # 3. Use a double-quoted here-string (@" ... "@) to print a tidy report
    #    that shows the name, IP, whether it's online, the service count,
    #    and the services joined with ", " (use $($services -join ', ')).
    #
    # ✅ Example output:
    #    Server:   WebServer01
    #    IP:       192.168.1.10
    #    Online:   True
    #    Services: 3 (DNS, Web, SQL)
    
    # your code here
    This is real code — run it for free atonecompiler.com/powershellor in your own editor.

    🎉 Lesson Complete!

    • ✅ Variables start with $ and are dynamically typed: String, Int32, Double, Boolean, plus $null
    • Double quotes expand variables and $(...); single quotes are literal
    • ✅ Wrap property/expression access in a $(...) subexpression inside strings
    • ✅ Build collections with @() (arrays) and @{ } (hashtables)
    • ✅ Cast with [int] / [double]; remember + follows the left-hand type
    • ✅ Here-strings (@" ... "@) keep multi-line text tidy
    • Next lesson: Working with Objects — pipe data between cmdlets and inspect their properties

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service