diff --git a/src/app/core/models/planned-term.ts b/src/app/core/models/planned-term.ts
index c29c4aadef34ad42fea8d1bb5ab181270f49327a..f6a334e2f36a4a931da0ee6781100fac18c3f2df 100644
--- a/src/app/core/models/planned-term.ts
+++ b/src/app/core/models/planned-term.ts
@@ -11,6 +11,6 @@ export interface PlannedTerm {
   termCode: TermCode;
   era: PlannedTermEra;
   note?: PlannedTermNote;
-  plannedCourses: Course[];
-  enrolledCourses: Course[];
+  plannedCourses: ReadonlyArray<Course>;
+  enrolledCourses: ReadonlyArray<Course>;
 }
diff --git a/src/app/core/models/year.ts b/src/app/core/models/year.ts
index 938ff3d31751ccaf0e3e33874170a5555561fd78..c8dcef8dcc2d366381735ee73721a7516ed72bb5 100644
--- a/src/app/core/models/year.ts
+++ b/src/app/core/models/year.ts
@@ -9,6 +9,10 @@ export interface Year {
   summer: PlannedTerm;
 }
 
-export interface YearMapping {
+export interface MutableYearMapping {
   [yearCode: string]: Year;
 }
+
+export interface YearMapping {
+  readonly [yearCode: string]: Year;
+}
diff --git a/src/app/degree-planner/course-search/course-search.component.ts b/src/app/degree-planner/course-search/course-search.component.ts
index 28f9d002e36d917f216384d10426c47bf4cac438..395a9711ad2feeaa61c07a9d261416d6e45f7602 100644
--- a/src/app/degree-planner/course-search/course-search.component.ts
+++ b/src/app/degree-planner/course-search/course-search.component.ts
@@ -36,7 +36,7 @@ export class CourseSearchComponent implements OnInit, OnDestroy {
 
   // Observable used for drag and drop and for populating term select
   public dropZoneIds$: Observable<string[]>;
-  public activeTerms$: Observable<TermCode[]>;
+  public activeTerms$: Observable<ReadonlyArray<TermCode>>;
   public activeSelectedSearchTerm$: Observable<TermCode | undefined>;
   public isCourseSearchOpen$: Observable<boolean>;
 
diff --git a/src/app/degree-planner/degree-planner.component.ts b/src/app/degree-planner/degree-planner.component.ts
index 075d5a98babacdb98e7e54f65d6b397a94b27dba..4858e43c5ffde65aca39971061420b2957aeb8cc 100644
--- a/src/app/degree-planner/degree-planner.component.ts
+++ b/src/app/degree-planner/degree-planner.component.ts
@@ -45,10 +45,10 @@ export class DegreePlannerComponent implements OnInit, OnDestroy {
   public mobileView: MediaQueryList;
   public coursesData$: any;
   public degreePlan$: Observable<DegreePlan | undefined>;
-  public allDegreePlans$: Observable<DegreePlan[]>;
+  public allDegreePlans$: Observable<ReadonlyArray<DegreePlan>>;
   public firstActiveTermCode$: Observable<TermCode | undefined>;
-  public termsByYear$: Observable<Year[]>;
-  public yearCodes$: Observable<YearCode[]>;
+  public termsByYear$: Observable<ReadonlyArray<Year>>;
+  public yearCodes$: Observable<ReadonlyArray<YearCode>>;
   public isCourseSearchOpen$: Observable<boolean>;
   public isLoadingPlan$: Observable<boolean>;
   public activeTermSubscription: Subscription;
diff --git a/src/app/degree-planner/saved-for-later-container/saved-for-later-container.component.ts b/src/app/degree-planner/saved-for-later-container/saved-for-later-container.component.ts
index 8c52be1a36fbe234d89cea368ee85d2d45fdd915..da06766b406645b5471c32704d1ace34f0ee1e57 100644
--- a/src/app/degree-planner/saved-for-later-container/saved-for-later-container.component.ts
+++ b/src/app/degree-planner/saved-for-later-container/saved-for-later-container.component.ts
@@ -23,7 +23,7 @@ import { MediaMatcher } from '@angular/cdk/layout';
   styleUrls: ['./saved-for-later-container.component.scss'],
 })
 export class SavedForLaterContainerComponent implements OnInit {
-  public courses$: Observable<SavedForLaterCourse[]>;
+  public courses$: Observable<ReadonlyArray<SavedForLaterCourse>>;
   public dropZoneIds$: Observable<string[]>;
   public mobileView: MediaQueryList;
 
diff --git a/src/app/degree-planner/shared/course-item/course-item.component.ts b/src/app/degree-planner/shared/course-item/course-item.component.ts
index 34f09d6d1eeb6070bf93a002b750b44b88e06109..d0dc1ebccf59d1037ee92359cd8394c5364fa399 100644
--- a/src/app/degree-planner/shared/course-item/course-item.component.ts
+++ b/src/app/degree-planner/shared/course-item/course-item.component.ts
@@ -48,7 +48,7 @@ export class CourseItemComponent implements OnInit {
   public visibleTermCodes$: Observable<string[]>;
   public droppableTermCodes$: Observable<string[]>;
   public term$: Observable<PlannedTerm>;
-  public plannedCourses: Course[];
+  public plannedCourses: ReadonlyArray<Course>;
   public toActiveTerm: boolean;
   public isStruckthrough = false;
 
diff --git a/src/app/degree-planner/shared/utils.ts b/src/app/degree-planner/shared/utils.ts
index f9444bdb7358c2f5ccda0891976a704510ca5b06..a684d6ae62e04681198043443e21c9d3493c1f4e 100644
--- a/src/app/degree-planner/shared/utils.ts
+++ b/src/app/degree-planner/shared/utils.ts
@@ -24,7 +24,7 @@ export const pickTermName = (termOffset: string) => {
 
 export const pickTermEra = (
   termCode: TermCode,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
 ): PlannedTermEra => {
   const noActiveTermCodes = activeTermCodes.length === 0;
   const isActiveTermCode = activeTermCodes.some(tc => tc.equals(termCode));
@@ -42,7 +42,7 @@ export const pickTermEra = (
 
 export const pickYearEra = (
   yearCode: YearCode,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
 ): PlannedTermEra => {
   const activeYearCodes = activeTermCodes.map(tc => tc.yearCode);
   const noActiveYearCodes = activeYearCodes.length === 0;
diff --git a/src/app/degree-planner/store/effects/plan.effects.ts b/src/app/degree-planner/store/effects/plan.effects.ts
index 59c69d36c00fc1049cafb1d13967d41f7c6156d2..7687b9dc95495a43b86855a630c3ebb5318c34ec 100644
--- a/src/app/degree-planner/store/effects/plan.effects.ts
+++ b/src/app/degree-planner/store/effects/plan.effects.ts
@@ -47,7 +47,7 @@ import {
   DegreePlannerState,
   INITIAL_DEGREE_PLANNER_STATE,
 } from '@app/degree-planner/store/state';
-import { YearMapping } from '@app/core/models/year';
+import { YearMapping, MutableYearMapping } from '@app/core/models/year';
 import { Note } from '@app/core/models/note';
 import { CourseBase, Course } from '@app/core/models/course';
 import { pickTermEra } from '@app/degree-planner/shared/utils';
@@ -382,10 +382,13 @@ const toYearCode = (termCode: string) => {
 
 const buildTerm = (
   termCode: TermCode,
-  notes: Note[],
+  notes: ReadonlyArray<Note>,
   subjects: SubjectMapping,
-  courses: { termCode: string; courses: CourseBase[] }[],
-  activeTermCodes: TermCode[],
+  courses: ReadonlyArray<{
+    termCode: string;
+    courses: ReadonlyArray<CourseBase>;
+  }>,
+  activeTermCodes: ReadonlyArray<TermCode>,
 ): PlannedTerm => {
   const baseNote = notes.find(matchesTermCode(termCode));
   const note: PlannedTermNote | undefined = baseNote
@@ -425,7 +428,7 @@ const loadPlanYears = (
   api: DegreePlannerApiService,
   roadmapId: number,
   subjects: SubjectMapping,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
 ): Observable<YearMapping> => {
   const notesAndCourses$ = forkJoinWithKeys({
     notes: api.getAllNotes(roadmapId),
@@ -454,7 +457,7 @@ const loadPlanYears = (
 
   const visibleYears$ = uniqueYearCodes$.pipe(
     map(({ uniqueYearCodes, notes, courses }) => {
-      const mapping: YearMapping = {};
+      const mapping: MutableYearMapping = {};
       uniqueYearCodes.forEach(yearCode => {
         mapping[yearCode.toString()] = {
           yearCode,
@@ -483,7 +486,7 @@ const loadPlanYears = (
         };
       });
 
-      return mapping;
+      return mapping as YearMapping;
     }),
   );
 
diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts
index 74b2686bf1a82f0cba5ebc57f876d9593ba82c92..1ab0783162a4dc145353c0c13dc04abb80b6fb2b 100644
--- a/src/app/degree-planner/store/reducer.ts
+++ b/src/app/degree-planner/store/reducer.ts
@@ -580,7 +580,10 @@ const emptyTerm = (termCode: TermCode, era: PlannedTermEra): PlannedTerm => {
   return { termCode, era, plannedCourses: [], enrolledCourses: [] };
 };
 
-const emptyYear = (yearCode: YearCode, activeTermCodes: TermCode[]): Year => {
+const emptyYear = (
+  yearCode: YearCode,
+  activeTermCodes: ReadonlyArray<TermCode>,
+): Year => {
   return {
     yearCode,
     isExpanded: utils.pickYearEra(yearCode, activeTermCodes) !== 'past',
@@ -598,7 +601,7 @@ const emptyYear = (yearCode: YearCode, activeTermCodes: TermCode[]): Year => {
 
 const generateYearForTermCode = (
   termCode: TermCode,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
 ): Year => {
   return emptyYear(termCode.yearCode, activeTermCodes);
 };
@@ -606,7 +609,7 @@ const generateYearForTermCode = (
 const createYearWithNote = (
   termCode: TermCode,
   note: PlannedTermNote | undefined,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
   year = generateYearForTermCode(termCode, activeTermCodes),
 ): Year => {
   const term = year[termCode.termName];
@@ -615,7 +618,7 @@ const createYearWithNote = (
 
 const createYearWithoutNote = (
   termCode: TermCode,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
   year?: Year,
 ) => {
   return createYearWithNote(termCode, undefined, activeTermCodes, year);
@@ -636,7 +639,7 @@ const findCourse = (
 const createYearWithCourse = (
   termCode: TermCode,
   course: Course,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
   year = generateYearForTermCode(termCode, activeTermCodes),
   newIndex?: number,
 ): Year => {
@@ -652,7 +655,7 @@ const createYearWithCourse = (
 const createYearWithoutCourse = (
   termCode: TermCode,
   recordId: number,
-  activeTermCodes: TermCode[],
+  activeTermCodes: ReadonlyArray<TermCode>,
   year = generateYearForTermCode(termCode, activeTermCodes),
 ): Year => {
   const term = year[termCode.termName];
diff --git a/src/app/degree-planner/store/state.ts b/src/app/degree-planner/store/state.ts
index b40df41cdc99afca4a578b93c07a198bfa960bf8..7f6ec06e5168b0b98d390046d4dd0b8ff314c0b2 100644
--- a/src/app/degree-planner/store/state.ts
+++ b/src/app/degree-planner/store/state.ts
@@ -8,9 +8,9 @@ import { TermCode } from '@app/core/models/termcode';
 export interface DegreePlannerState {
   visibleDegreePlan: DegreePlan | undefined;
   visibleYears: YearMapping;
-  savedForLaterCourses: SavedForLaterCourse[];
-  activeTermCodes: TermCode[];
-  allDegreePlans: DegreePlan[];
+  savedForLaterCourses: ReadonlyArray<SavedForLaterCourse>;
+  activeTermCodes: ReadonlyArray<TermCode>;
+  allDegreePlans: ReadonlyArray<DegreePlan>;
   subjects: SubjectMapping;
   subjectDescriptions: SubjectMapping;
   search: { visible: boolean; selectedTerm?: TermCode };
diff --git a/src/app/degree-planner/term-container/term-container.component.ts b/src/app/degree-planner/term-container/term-container.component.ts
index 18a7003db1645ae3323145e5b51632cae9fb657c..7b6438a1d4a3cc89dd9b7ba0f038babfa5731413 100644
--- a/src/app/degree-planner/term-container/term-container.component.ts
+++ b/src/app/degree-planner/term-container/term-container.component.ts
@@ -48,14 +48,14 @@ export class TermContainerComponent implements OnInit, OnDestroy {
   public termSubscription: Subscription;
   public activeTermHasNotOffered: boolean;
   // List of courses pulled for the Observable
-  public plannedCourses: Course[];
-  public enrolledCourses: Course[];
+  public plannedCourses: ReadonlyArray<Course>;
+  public enrolledCourses: ReadonlyArray<Course>;
   public era: 'past' | 'active' | 'future';
   public hasItemDraggedOver: boolean;
   public plannedCredits: string;
   public enrolledCredits: number;
   public visibleCredits: 'enrolled' | 'planned';
-  public courseNotOfferedInTerm: Course[];
+  public courseNotOfferedInTerm: ReadonlyArray<Course>;
   public mobileView: MediaQueryList;
 
   constructor(
@@ -291,11 +291,11 @@ export class TermContainerComponent implements OnInit, OnDestroy {
     this.hasItemDraggedOver = false;
   }
 
-  sumEnrolledCredits(courses: Course[]): number {
+  sumEnrolledCredits(courses: ReadonlyArray<Course>): number {
     return courses.reduce((sum, course) => sum + course.credits, 0);
   }
 
-  sumPlannedCredits(courses: Course[]): string {
+  sumPlannedCredits(courses: ReadonlyArray<Course>): string {
     const credits = { min: 0, max: 0 };
     courses.forEach(course => {
       credits.min = credits.min + course.creditMin;