Functions
By the end of this lesson you'll be able to type a function's parameters and return value, make arguments optional or give them defaults, accept any number of arguments, describe a function as a type, and write overloads — so TypeScript catches a wrong call before your code ever runs.
Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.
Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
A typed function is like a vending machine . The coin slot only accepts the right shape (the parameter types), and the tray always delivers the kind of item you expect (the return type). Put in the wrong coin and the machine rejects it at the slot — it doesn't take your money, jam, and break halfway through. TypeScript is that coin slot: it rejects a bad call at the door , before the machine ever runs, instead of crashing mid-purchase like plain JavaScript would.
1. Typing Parameters & Return Values
In TypeScript you add a type annotation after each parameter and after the parentheses for the return value. The shape is always function name(param: Type): ReturnType . This is the single most useful thing TypeScript adds to JavaScript: call the function with the wrong kind of value and you get a red squiggle in your editor, not a 2am production crash.
A return type of void means "this function doesn't hand a value back" — you call it for its effect (printing, saving) not its result. Run the worked example below; it's the same code with annotations removed so it executes as JavaScript.
2. Optional & Default Parameters
Sometimes a parameter isn't always needed. Add ? after its name to make it optional — TypeScript then treats it as possibly undefined , so you must handle that case. Or give it a default value with = value : if the caller leaves it out, the default is used automatically. A default also makes the parameter optional, but you never have to check for undefined .
Now you try. The program below is almost complete — fill in the two blanks marked ___ using the hints, then run it and check your output.
3. Rest Params, Arrows & Function Types
A rest parameter ( ...numbers: number[] ) collects "any number of" trailing arguments into a typed array — perfect when you don't know how many you'll get. An arrow function is a compact way to write a function: . And a function type expression lets you describe a function's shape as a reusable type, so you can pass functions around with full type safety.
Read the worked example, then run it. Notice how applyOp takes a function as an argument — that's only safe because MathOp pins down exactly what that function must look like.
Your turn again — finish the average function. It uses a rest parameter and an arrow inside reduce . Fill in the two blanks:
4. Function Overloads
An overload lets one function advertise several different typed call signatures. You write the signatures first (no body), then one implementation that handles them all. Callers only ever see the clean, specific signatures — TypeScript hides the messy string | number implementation underneath. This is how you say "this function behaves differently depending on what you give it" while keeping every call fully type-checked.
Run the worked version below. The behaviour branches on typeof value at runtime, while the overload signatures give callers precise, safe types at compile time.
Arrow functions aren't just "shorter function ". The key difference is this : an arrow function does not create its own this — it borrows the one from where it was written. That makes arrows the right choice for callbacks (like inside map , filter , reduce , or event handlers) where you want to keep the surrounding this .
For a one-line return you can drop the braces and the word return : . If you need braces for multiple statements, you must write return yourself.
This small function uses everything from the lesson at once: a required parameter, a default parameter, a rest parameter, and an explicit string return type. Read it line by line — you understand every part now.
Order matters: the required base comes first, then the taxRate with its default, then the ...fees rest parameter — which must always be last .
Q: What's the difference between ? and = default ?
Both let the caller skip the argument. With ? the parameter can be undefined , so you must handle that. With = value it falls back to that value automatically, so it's never undefined inside the function.
Q: Do I always have to write the return type?
No — TypeScript usually infers it from your return statements. But writing it is good practice: it documents intent and turns a wrong return into an error at the function, not at some far-away call site.
Q: When should I use overloads instead of a union type?
Use a union ( string | number ) when the return type is the same no matter the input. Use overloads when the relationship between input and output changes — e.g. a string input returns a string and a number input returns a number array.
Q: Is an arrow function the same as a regular function?
Almost — the big difference is this . Arrow functions don't bind their own this ; they reuse the one from where they're defined, which makes them ideal for callbacks. For most plain helper functions, either style works.
No blanks this time — just a brief and an outline. Write the body yourself using a default parameter and a rest parameter, run it, and check your output against the expected lines.
Practice quiz
What is the shape of a typed function declaration?
- function name(param): Type { }
- function name<Type>(param) { }
- function name(param: Type): ReturnType { }
- function name: ReturnType(param) { }
Answer: function name(param: Type): ReturnType { }. Annotate each parameter (param: Type) and the return type after the parentheses.
What return type marks a function that returns nothing useful?
- void
- null
- undefined
- never
Answer: void. void means the function is called for its effect, not its result.
What is the difference between '?' and '= default' on a parameter?
- No difference
- '?' sets a value; '= value' makes it optional
- Only '?' works in strict mode
- '?' may be undefined (you must handle it); '= value' falls back automatically
Answer: '?' may be undefined (you must handle it); '= value' falls back automatically. Optional parameters can be undefined; default parameters supply a value so they are never undefined.
What does a rest parameter '...numbers: number[]' do?
- Accepts exactly one array
- Collects any number of trailing arguments into a typed array
- Spreads an array into arguments
- Marks the parameter optional
Answer: Collects any number of trailing arguments into a typed array. A rest parameter gathers the remaining arguments into an array.
Where must optional, default, and rest parameters appear?
- After the required ones
- Before required ones
- Anywhere
- Only alone
Answer: After the required ones. Required parameters come first; optional/default/rest must follow them (rest always last).
Which error fires when you forget to type a parameter under strict mode?
- TS2322
- TS2554
- TS7006: Parameter implicitly has an 'any' type
- TS2355
Answer: TS7006: Parameter implicitly has an 'any' type. noImplicitAny (on in strict mode) raises TS7006 for an untyped parameter.
An arrow function with braces and multiple statements must:
- Omit the return
- Write 'return' explicitly
- Use the function keyword
- Be a method
Answer: Write 'return' explicitly. Implicit return only works for a single expression; with braces you must write return.
Compared with a regular function, an arrow function's key difference is:
- It is faster
- It cannot take arguments
- It always returns void
- It does not bind its own 'this' — it captures the surrounding one
Answer: It does not bind its own 'this' — it captures the surrounding one. Arrow functions reuse the enclosing this, which makes them ideal for callbacks.
What do function overloads let one function do?
- Run twice
- Advertise several typed call signatures over one implementation
- Skip type checking
- Return any type
Answer: Advertise several typed call signatures over one implementation. You write several signatures, then one implementation; callers see only the clean signatures.
When should you use a union type instead of overloads?
- Always
- When the input is an array
- When the return type is the same regardless of the input
- Never
Answer: When the return type is the same regardless of the input. A union like string | number is enough when the return type does not vary by input.