Everyday TypeScript: Shared Fields
Welcome to the Shared Fields lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
Sometimes, we want a discriminated union with a field shared in both cases. For example,
StartedCourses andUnstartedCourses both havenames. We could choose to duplicate thenamefield:>
type StartedCourse = {name: stringstarted: truelastInteractionTime: Date};type UnstartedCourse = {name: stringstarted: false};type Course = StartedCourse | UnstartedCourse;- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
let course: Course = {name: 'typescript',started: false,};course.name;Result:
'typescript'
This works, but it can get wordy with many shared fields. (Imagine
StartedCourseandUnstartedCoursesharing ten fields!) We can eliminate the duplication by moving the shared fields into a shared type.>
type CourseShared = {name: string};type StartedCourse = CourseShared & {started: truelastInteractionTime: Date};type UnstartedCourse = CourseShared & {started: false};type Course = StartedCourse | UnstartedCourse;- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
let course: Course = {name: 'typescript',started: false,};course.name;Result:
'typescript'
This raises a question of style. Should we define four named types:
CourseShared,StartedCourse,UnstartedCourse, andCourse? Or should we combine them all into a single type definition? Either way works.The version of
Coursebelow is completely equivalent to the one above!>
type Course = {name: string} & ({started: truelastInteractionTime: Date} | {started: false});- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
let course: Course = {name: 'typescript',started: false,};course.name;Result:
'typescript'
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
let course: Course = {name: 'typescript',started: false,lastInteractionTime: new Date(),};course.name;Result:
type error: Object literal may only specify known properties, and 'lastInteractionTime' does not exist in type '{ name: string; } & { started: false; }'. But that type is a bit hard to read. It's often better to name the pieces of a type as you build it up.