MODELING DATA · LESSON 5 OF 24
Objects, interfaces and type aliases
Define reusable object contracts and understand structural compatibility.
- interface
- type
- optional
- structural typing
Your runnable checkpoint
Extract into a new practice folder. Each download includes complete source, package.json, tsconfig.json and an offline lesson. Use Node.js 22 or 24. Each checkpoint is independent.
Install with npm install. Run npm run check, then npm run build. Terminal lessons use npm start; browser lessons use npm run serve and http://127.0.0.1:4173.
1. Understand the concepts
An interface describes an object shape and can extend another interface. A type alias can name an object, union, tuple or other type expression. Both are useful; pick a consistent style and choose based on the relationship you need to express.
TypeScript compares most object types structurally: a value is compatible when it has the required members with compatible types. It does not require an explicit declaration that an object implements an interface.
An optional property may be absent. With exactOptionalPropertyTypes enabled, email?: string permits omission but not an explicitly assigned undefined value unless undefined is included in the type. Reading it can still produce undefined.
Excess-property checks help catch misspellings on fresh object literals. They are not a general runtime validator and do not imply that compatible objects have no additional fields. readonly restricts writes through a type, not runtime mutation everywhere.
2. Build and run
These are complete files. Preserve the paths shown below, including the src directory. The package and compiler configuration are included at the end.
src/main.ts
interface Person {
readonly id: number;
name: string;
email?: string;
}
interface Student extends Person {
course: string;
}
type StudentCard = Pick<Student, "name" | "course">;
function label(person: Person): string {
return `${person.name} (${person.email ?? "no email"})`;
}
const student: Student = { id: 1, name: "Asha", course: "TypeScript" };
const card: StudentCard = { name: student.name, course: student.course };
console.log(label(student));
console.log(card.course);
package.json
{
"name": "edupoly-typescript-objects-interfaces-and-aliases",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"check": "tsc --noEmit",
"build": "tsc",
"start": "node dist/main.js"
},
"devDependencies": {
"typescript": "5.9.3"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": [
"ES2022",
"DOM"
],
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noEmitOnError": true,
"verbatimModuleSyntax": true,
"rootDir": "src",
"outDir": "dist",
"sourceMap": true,
"types": [],
"moduleDetection": "force"
},
"include": [
"src/**/*"
]
}
3. Trace the code and check the result
- Student inherits the Person members.
- label accepts a Student because it contains the Person shape.
- Pick creates a smaller view; it does not remove fields from an existing object at runtime.
Expected result
Asha (no email)
TypeScript4. Practice independently
Add an optional graduationYear and print a fallback when it is absent.
Show the explanation
Declare graduationYear?: number. Display student.graduationYear ?? "Not set". Do not assign undefined unless you explicitly add it to the property type.
When something goes wrong
If tsc is missing, run npm install in the folder containing package.json. If the output looks old, rebuild before running. Read the first compiler diagnostic and check the indicated field or argument. For module errors, preserve the .js extensions in imports. Browser examples must run through the included local server, not directly as TypeScript files.
