Skip to content

Object Types

Objects are the most common data structure in JavaScript. TypeScript lets you describe their shape with a type annotation that lists each property name and its type. This lesson covers inline object types — Module 03 gives these shapes names with interfaces and type aliases.

An object type lists property names and their types, separated by semicolons, inside curly braces:

const question: { text: string; correctAnswer: string; difficulty: string } = {
text: 'What planet is closest to the Sun?',
correctAnswer: 'Mercury',
difficulty: 'easy',
};

TypeScript checks two things: that all declared properties exist, and that their values match the declared types.

Once an object is typed, TypeScript knows exactly what properties are available and what their types are:

console.log(question.text.toUpperCase()); // ✓ — text is string
console.log(question.difficulty.toFixed(2)); // Error: Property 'toFixed' does not exist on type 'string'
console.log(question.category); // Error: Property 'category' does not exist

The third error — accessing a property that was not declared — is TypeScript preventing the undefined property access that JavaScript silently returns undefined for.

TypeScript uses structural typing: a value is compatible with a type if it has at least the required properties with the right types. It does not need to be the exact same declared type.

function printQuestion(q: { text: string; correctAnswer: string }): void {
console.log(q.text, '', q.correctAnswer);
}
const fullQuestion = {
text: 'What planet is closest to the Sun?',
correctAnswer: 'Mercury',
difficulty: 'easy', // extra property
};
printQuestion(fullQuestion); // ✓ — has the required properties, extra ones are fine

The object fullQuestion has more properties than printQuestion requires, but it satisfies the type because it has everything that was asked for. This is structural (or “duck”) typing — if it has the right shape, it fits.

Object types can nest:

const highScore: { score: number; meta: { date: string; total: number } } = {
score: 8,
meta: {
date: '2024-01-15',
total: 10,
},
};
console.log(highScore.meta.date); // '2024-01-15'

Deeply nested inline types become hard to read quickly. Module 03 introduces interfaces, which let you name these shapes and reuse them — HighScore, TriviaQuestion, ApiResponse.

AceIt fetches questions from the Open Trivia DB. Before you formalize the shape with an interface, you can describe it inline:

const raw: {
type: string;
difficulty: string;
category: string;
question: string;
correct_answer: string;
incorrect_answers: string[];
} = await response.json();

Every property from the API is declared. TypeScript knows that raw.correct_answer is a string and that raw.incorrect_answers is an array of strings. Accessing raw.correctAnswer (camelCase, not matching the API) would be an error — catching a common bug when adapting snake_case API responses.

A property can be marked optional with ?. Optional properties may be present or absent:

const result: { score: number; message?: string } = { score: 7 };
// message is not required — no error
if (result.message) {
console.log(result.message.toUpperCase()); // safe to use inside the guard
}

Outside the if check, TypeScript knows message could be undefined. Attempting to call .toUpperCase() on it directly would be an error. This is strictNullChecks at work — it forces you to check before use.

In types.ts inside your aceit/ folder, write inline object types for the following — do not use interfaces yet:

  1. A variable sampleQuestion typed as an object with text: string, category: string, difficulty: string, correctAnswer: string, and allAnswers: string[]. Populate it with real values.
  2. A function isCorrect(selected: string, question: { correctAnswer: string }): boolean that returns true if selected matches question.correctAnswer.
  3. A variable entry typed as { score: number; total: number; date?: string }. Assign it with date present, then without — confirm both compile.
  • Object types list property names and types inside curly braces.
  • TypeScript uses structural typing — an object fits a type if it has at least the required properties.
  • Accessing undeclared properties is a compile error — preventing the silent undefined JavaScript returns.
  • Optional properties (?) can be absent — TypeScript requires a check before using their value.
  • Inline object types work for simple cases; Module 03 introduces interfaces for naming and reusing shapes.