diff --git a/app/javascript/mastodon/actions/app.js b/app/javascript/mastodon/actions/app.js
deleted file mode 100644
index c817c87080..0000000000
--- a/app/javascript/mastodon/actions/app.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export const APP_FOCUS   = 'APP_FOCUS';
-export const APP_UNFOCUS = 'APP_UNFOCUS';
-
-export const focusApp = () => ({
-  type: APP_FOCUS,
-});
-
-export const unfocusApp = () => ({
-  type: APP_UNFOCUS,
-});
-
-export const APP_LAYOUT_CHANGE = 'APP_LAYOUT_CHANGE';
-
-export const changeLayout = layout => ({
-  type: APP_LAYOUT_CHANGE,
-  layout,
-});
diff --git a/app/javascript/mastodon/actions/app.ts b/app/javascript/mastodon/actions/app.ts
new file mode 100644
index 0000000000..0acfbfae7a
--- /dev/null
+++ b/app/javascript/mastodon/actions/app.ts
@@ -0,0 +1,10 @@
+import { createAction } from '@reduxjs/toolkit';
+
+export const focusApp = createAction('APP_FOCUS');
+export const unfocusApp = createAction('APP_UNFOCUS');
+
+type ChangeLayoutPayload = {
+  layout: 'mobile' | 'single-column' | 'multi-column';
+};
+export const changeLayout =
+  createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE');
diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx
index 2178687a9e..6dc5177b5c 100644
--- a/app/javascript/mastodon/features/ui/index.jsx
+++ b/app/javascript/mastodon/features/ui/index.jsx
@@ -362,7 +362,7 @@ class UI extends React.PureComponent {
 
     if (layout !== this.props.layout) {
       this.handleLayoutChange.cancel();
-      this.props.dispatch(changeLayout(layout));
+      this.props.dispatch(changeLayout({ layout }));
     } else {
       this.handleLayoutChange();
     }
diff --git a/app/javascript/mastodon/reducers/meta.js b/app/javascript/mastodon/reducers/meta.js
index 755dd73905..16ce751aad 100644
--- a/app/javascript/mastodon/reducers/meta.js
+++ b/app/javascript/mastodon/reducers/meta.js
@@ -1,5 +1,5 @@
 import { STORE_HYDRATE } from 'mastodon/actions/store';
-import { APP_LAYOUT_CHANGE } from 'mastodon/actions/app';
+import { changeLayout } from 'mastodon/actions/app';
 import { Map as ImmutableMap } from 'immutable';
 import { layoutFromWindow } from 'mastodon/is_mobile';
 
@@ -14,8 +14,8 @@ export default function meta(state = initialState, action) {
   switch(action.type) {
   case STORE_HYDRATE:
     return state.merge(action.state.get('meta')).set('permissions', action.state.getIn(['role', 'permissions']));
-  case APP_LAYOUT_CHANGE:
-    return state.set('layout', action.layout);
+  case changeLayout.type:
+    return state.set('layout', action.payload.layout);
   default:
     return state;
   }
diff --git a/app/javascript/mastodon/reducers/missed_updates.js b/app/javascript/mastodon/reducers/missed_updates.js
deleted file mode 100644
index a3141d854e..0000000000
--- a/app/javascript/mastodon/reducers/missed_updates.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Map as ImmutableMap } from 'immutable';
-import { NOTIFICATIONS_UPDATE } from 'mastodon/actions/notifications';
-import { APP_FOCUS, APP_UNFOCUS } from 'mastodon/actions/app';
-
-const initialState = ImmutableMap({
-  focused: true,
-  unread: 0,
-});
-
-export default function missed_updates(state = initialState, action) {
-  switch(action.type) {
-  case APP_FOCUS:
-    return state.set('focused', true).set('unread', 0);
-  case APP_UNFOCUS:
-    return state.set('focused', false);
-  case NOTIFICATIONS_UPDATE:
-    return state.get('focused') ? state : state.update('unread', x => x + 1);
-  default:
-    return state;
-  }
-}
diff --git a/app/javascript/mastodon/reducers/missed_updates.ts b/app/javascript/mastodon/reducers/missed_updates.ts
new file mode 100644
index 0000000000..043fe93faf
--- /dev/null
+++ b/app/javascript/mastodon/reducers/missed_updates.ts
@@ -0,0 +1,31 @@
+import { Record } from 'immutable';
+import type { Action } from 'redux';
+import { NOTIFICATIONS_UPDATE } from '../actions/notifications';
+import { focusApp, unfocusApp } from '../actions/app';
+
+type MissedUpdatesState = {
+  focused: boolean;
+  unread: number;
+};
+const initialState = Record<MissedUpdatesState>({
+  focused: true,
+  unread: 0,
+})();
+
+export default function missed_updates(
+  state = initialState,
+  action: Action<string>,
+) {
+  switch (action.type) {
+  case focusApp.type:
+    return state.set('focused', true).set('unread', 0);
+  case unfocusApp.type:
+    return state.set('focused', false);
+  case NOTIFICATIONS_UPDATE:
+    return state.get('focused')
+      ? state
+      : state.update('unread', (x) => x + 1);
+  default:
+    return state;
+  }
+}