Basic types and inference
Primitives, arrays, tuples, any, unknown, never and as const.
You rarely need to annotate everything: TypeScript infers most types and only asks when it cannot know. Interviewers probe whether you can read inference — what type does this variable actually have?
Real-life situation
A cart total breaks when the string "12" sneaks into a prices array.
JavaScript happily computes 0 + "12" as "012" and renders it. With
prices: number[], the mistake fails at the line that introduces it,
not at the customer. That is the whole pitch for basic types.
Visual
Try it
Checked with TypeScript 6.0.3, strict mode
function cartTotal(prices: number[]): number {
let total = 0;
for (const price of prices) {
total = total + price;
}
return total;
}
const prices: number[] = [12, 8, 20];
console.log("items: " + prices.length);
console.log("total: " + cartTotal(prices));
const pair: [string, number] = ["book", 12];
console.log(pair[0] + " costs " + pair[1]);
const frozen = ["book", "pen"] as const;
console.log(frozen.length);
const typo: number = "12";
console.log("total: " + cartTotal([typo]));Compiler not loaded. Check or Run loads it here (about 9 MB) — nothing downloads until you do.
Try changing "12" to 12 and watch the error vanish. Then hover over
pair and frozen mentally: the tuple keeps position types, while as const freezes the array into readonly literals. Remove the : number[]
annotation and nothing changes — inference already knew.
Primitives (string, number, boolean) plus null and undefined
cover most values. any opts out of checking, unknown forces you to
check first, and never marks code that cannot return — each gets its
own page later (any versus unknown).
Will it compile? — decide first, then reveal.
const total: number = "five";
console.log(total);Interview questions
What are the most common basic types in TypeScript?basic
You will use string, number, boolean, null, and undefined for everyday values, plus bigint and symbol for rarer cases. Arrays are written string[] and objects get inline shapes like { name: string }. void marks functions that return nothing useful. Start with these small building blocks — every interface, union, and generic you meet later is composed from them.
Interviewers also ask
- How do you write the type of an array of strings?
How do you add a type annotation to a variable?basic
You add a colon plus the type after the name, like let name: string = 'Asha'. The annotation tells the compiler what you intend, and it rejects any later assignment that disagrees. You only need it where inference cannot figure things out — for empty declarations like let user: User or function boundaries. Inside a function body, prefer letting inference do the work so the code stays quiet.
Interviewers also ask
- When can you leave the annotation off?
How does type inference work, and when should you rely on it?basic
The compiler infers a type from the initializer, so let count = 0 is treated as number without you writing anything. Rely on it for locals — it keeps code short and stays accurate. Write explicit annotations at function parameters and return positions, where there is no initializer to learn from and where the annotation documents your contract for every caller. Hover over a variable in your editor to see what was inferred.
Interviewers also ask
- Where does inference fall short?
How do null and undefined differ in TypeScript?basic
undefined means a value is missing — an uninitialized variable or a skipped optional property. null means you deliberately set emptiness, like clearing a selected user. With strictNullChecks on, they are distinct types and you must handle each before use, which removes the classic Cannot read properties of null crash. Be explicit about which one your function accepts and returns.
Interviewers also ask
- What does strictNullChecks change here?
How do you type arrays in TypeScript?basic
You write the element type plus brackets, like string[] or number[], which is shorthand for Array<string>. The compiler then checks every element on creation and every access afterwards — pushing a number into a string[] is an error. Use readonly string[] when callers should not mutate the array. For fixed-length mixed shapes, reach for a tuple instead of a plain array.
Interviewers also ask
- When would you use a tuple instead of an array?
What is a tuple and when would you use one?basic
A tuple is a fixed-length array where each position has its own type, like [string, number] for a name-age pair. You annotate it with brackets around the sequence, and the compiler checks both the length and each slot's type. Use tuples for small, positionally meaningful returns such as [user, error] helpers. For anything with named fields, prefer an object — names document intent better than positions do.
Interviewers also ask
- How is [string, number] different from (string | number)[]?
What does void mean as a function return type?intermediate
void means the function returns nothing you should use — typical for callbacks, event handlers, and side-effect helpers. You can still return early with no value, but assigning the result is pointless. Do not confuse it with undefined as a value type: void describes intent at the function boundary, while undefined is a concrete value that can appear anywhere. Annotate effect-only functions : void to keep callers honest.
Interviewers also ask
- How is void different from undefined?
What does never mean, and when do you see it?intermediate
never marks values that cannot occur: a function that always throws or loops forever, or a code branch that should be unreachable. You meet it most in exhaustive switch statements, where narrowing every union member leaves never in the final default — assigning anything there proves a case was missed. It also appears when you intersect incompatible types. Treat a never sighting as the compiler telling you this path is impossible.
Interviewers also ask
- How does never help with exhaustive switches?
Key takeaways
- Annotate boundaries (function inputs, API shapes); let inference handle the rest.
- Tuples fix positions,
as constfreezes literals — arrays do neither. unknownis the honest default for data you have not checked yet.
Runner helpers
sleep(ms)waits;fakeFetch(url)returns deterministic sample data. TypeScript is stripped before running; imports and exports are not available in the sandbox.