From 2c2c856239e9c6f1b1d1d1af7b529dc1e725a903 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:13:52 -0800 Subject: [PATCH 01/11] TSConfig Type Checking This is the command I set up to demo this as well. `tsc --noEmit --skipLibCheck --target esnext --module nodenext ./**/*.ts` I have a 'template' config that I tend to start with, then I remove flags to make it on the same level as what the project needs, then bring flags back into place one by one, incrementally allowing for stronger type checking. :) So right now this simply allows you to run `tsc` on the project, and you get a list of all current errors and issues to focus on, without having to go to each file to find them. It helps for migrations and larger cross-project updates as well. --- tsconfig.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tsconfig.json diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..a9d4969e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "target": "ESNext", + // "isolatedModules": true, + "noEmit": true, + "skipLibCheck": true, // temp + // "strict": true, + // "noImplicitOverride": true, + // "noPropertyAccessFromIndexSignature": true, + // "noUncheckedIndexedAccess": true, + // "allowUnreachableCode": false, + // "noUnusedLocals": true, + // "allowUnusedLabels": false, + // "noUnusedParameters": true + } +} From acd5637ff946808609cc28d17249af76505eb4da Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:23:47 -0800 Subject: [PATCH 02/11] MidiInput Lib Typings --- editor/MidiInput.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editor/MidiInput.ts b/editor/MidiInput.ts index 7f1b1513..30dbf9f2 100644 --- a/editor/MidiInput.ts +++ b/editor/MidiInput.ts @@ -6,10 +6,13 @@ import {AnalogousDrum, analogousDrumMap, MidiEventType} from "./Midi.js"; declare global { interface Navigator { - requestMIDIAccess?(): Promise; + // Defined in latest TypeScript typings + // requestMIDIAccess?(): Promise; } } +// Maybe these can be moved to standard lib typings as well, will have to look into it further. + interface MIDIInput extends EventTarget { id: string; type: "input" | "output"; From b14305936079108859a6957004a5661270994832 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:24:28 -0800 Subject: [PATCH 03/11] PatternEditor Primitive Fix --- editor/PatternEditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/PatternEditor.ts b/editor/PatternEditor.ts index af521727..987fe0d9 100644 --- a/editor/PatternEditor.ts +++ b/editor/PatternEditor.ts @@ -178,7 +178,7 @@ export class PatternEditor { / minDivision) * minDivision; if (this._pattern != null) { - const cursorPartForMatching: Number = Math.max(0, Math.min(partsPerPattern - 1, this._cursor.exactPart)); + const cursorPartForMatching: number = Math.max(0, Math.min(partsPerPattern - 1, this._cursor.exactPart)); for (const note of this._pattern.notes) { if (note.end <= cursorPartForMatching) { this._cursor.prevNote = note; From abcfe09ff190d4dea749854f04bd80944be39628 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:27:17 -0800 Subject: [PATCH 04/11] Explicit Inheritance Overrides --- editor/Change.ts | 4 ++-- editor/changes.ts | 42 +++++++++++++++++++++--------------------- tsconfig.json | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/editor/Change.ts b/editor/Change.ts index 44edbf9d..096947d4 100644 --- a/editor/Change.ts +++ b/editor/Change.ts @@ -88,13 +88,13 @@ export class ChangeSequence extends UndoableChange { this._didSomething(); } - protected _doForwards(): void { + protected override _doForwards(): void { for (let i: number = 0; i < this._changes.length; i++) { this._changes[i].redo(); } } - protected _doBackwards(): void { + protected override _doBackwards(): void { for (let i: number = this._changes.length-1; i >= 0 ; i--) { this._changes[i].undo(); } diff --git a/editor/changes.ts b/editor/changes.ts index 87f390c9..0944a1f1 100644 --- a/editor/changes.ts +++ b/editor/changes.ts @@ -352,7 +352,7 @@ class ChangePins extends UndoableChange { this._didSomething(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._note.pins = this._newPins; this._note.pitches = this._newPitches; this._note.start = this._newStart; @@ -361,7 +361,7 @@ class ChangePins extends UndoableChange { if (this._doc != null) this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._note.pins = this._oldPins; this._note.pitches = this._oldPitches; this._note.start = this._oldStart; @@ -1304,7 +1304,7 @@ class ChangeInstrumentSlider extends Change { this._instrument = this._doc.song.channels[this._doc.channel].instruments[this._doc.getCurrentInstrument()]; } - public commit(): void { + public override commit(): void { if (!this.isNoop()) { this._instrument.preset = this._instrument.type; this._doc.notifier.changed(); @@ -1470,7 +1470,7 @@ export class ChangeFilterAddPoint extends UndoableChange { this.redo(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._filterSettings.controlPoints.splice(this._index, 0, this._point); this._filterSettings.controlPointCount++; this._filterSettings.controlPoints.length = this._filterSettings.controlPointCount; @@ -1482,7 +1482,7 @@ export class ChangeFilterAddPoint extends UndoableChange { this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._filterSettings.controlPoints.splice(this._index, 1); this._filterSettings.controlPointCount--; this._filterSettings.controlPoints.length = this._filterSettings.controlPointCount; @@ -1520,14 +1520,14 @@ export class ChangeFilterMovePoint extends UndoableChange { this.redo(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._point.freq = this._newFreq; this._point.gain = this._newGain; this._instrument.preset = this._instrumentNextPreset; this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._point.freq = this._oldFreq; this._point.gain = this._oldGain; this._instrument.preset = this._instrumentPrevPreset; @@ -1558,14 +1558,14 @@ export class ChangeFadeInOut extends UndoableChange { this.redo(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._instrument.fadeIn = this._newFadeIn; this._instrument.fadeOut = this._newFadeOut; this._instrument.preset = this._instrumentNextPreset; this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._instrument.fadeIn = this._oldFadeIn; this._instrument.fadeOut = this._oldFadeOut; this._instrument.preset = this._instrumentPrevPreset; @@ -1761,12 +1761,12 @@ export class ChangePitchAdded extends UndoableChange { this.redo(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._note.pitches.splice(this._index, 0, this._pitch); this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._note.pitches.splice(this._index, 1); this._doc.notifier.changed(); } @@ -1946,7 +1946,7 @@ export class ChangeEnsurePatternExists extends UndoableChange { this._doForwards(); } - protected _doForwards(): void { + protected override _doForwards(): void { const song: Song = this._doc.song; for (let j: number = song.patternsPerChannel; j < this._newPatternCount; j++) { for (let i: number = 0; i < song.getChannelCount(); i++) { @@ -1962,7 +1962,7 @@ export class ChangeEnsurePatternExists extends UndoableChange { this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { const song: Song = this._doc.song; const pattern: Pattern = song.channels[this._channelIndex].patterns[this._patternIndex - 1]; if (this._patternOldNotes != null) pattern.notes = this._patternOldNotes; @@ -2597,12 +2597,12 @@ export class ChangeNoteAdded extends UndoableChange { this.redo(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._pattern.notes.splice(this._index, 0, this._note); this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._pattern.notes.splice(this._index, 1); this._doc.notifier.changed(); } @@ -2831,13 +2831,13 @@ class ChangeTransposeNote extends UndoableChange { this._didSomething(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._note.pins = this._newPins; this._note.pitches = this._newPitches; this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._note.pins = this._oldPins; this._note.pitches = this._oldPitches; this._doc.notifier.changed(); @@ -2893,14 +2893,14 @@ export class ChangePatternSelection extends UndoableChange { this._didSomething(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._doc.selection.patternSelectionStart = this._newStart; this._doc.selection.patternSelectionEnd = this._newEnd; this._doc.selection.patternSelectionActive = this._newActive; this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._doc.selection.patternSelectionStart = this._oldStart; this._doc.selection.patternSelectionEnd = this._oldEnd; this._doc.selection.patternSelectionActive = this._oldActive; @@ -3131,12 +3131,12 @@ export class ChangeSizeBend extends UndoableChange { this._didSomething(); } - protected _doForwards(): void { + protected override _doForwards(): void { this._note.pins = this._newPins; this._doc.notifier.changed(); } - protected _doBackwards(): void { + protected override _doBackwards(): void { this._note.pins = this._oldPins; this._doc.notifier.changed(); } diff --git a/tsconfig.json b/tsconfig.json index a9d4969e..7237e5c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "noEmit": true, "skipLibCheck": true, // temp // "strict": true, - // "noImplicitOverride": true, + "noImplicitOverride": true, // "noPropertyAccessFromIndexSignature": true, // "noUncheckedIndexedAccess": true, // "allowUnreachableCode": false, From 3d85d7616fd7a6db2fd3f88f6a1823b2d2b22f33 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:33:42 -0800 Subject: [PATCH 05/11] Partial Strict Mode Enabled a few more flags, seemingly no errors for those (yay!). A few strict-related flags rose some errors, so those have been omitted for this commit, so they can be resolved each on their own. --- tsconfig.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 7237e5c8..056c7704 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,13 +5,15 @@ // "isolatedModules": true, "noEmit": true, "skipLibCheck": true, // temp - // "strict": true, + "strict": true, + "strictNullChecks": false, // temp + "strictPropertyInitialization": false, // temp "noImplicitOverride": true, // "noPropertyAccessFromIndexSignature": true, // "noUncheckedIndexedAccess": true, // "allowUnreachableCode": false, - // "noUnusedLocals": true, - // "allowUnusedLabels": false, + "noUnusedLocals": true, + "allowUnusedLabels": false, // "noUnusedParameters": true } } From 44d800249a98242fc3a22c8a942c2a35c78f672c Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:37:29 -0800 Subject: [PATCH 06/11] Null Checks Enabled Errors present! Will resolve next commit. --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 056c7704..076b4a52 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "noEmit": true, "skipLibCheck": true, // temp "strict": true, - "strictNullChecks": false, // temp + // "strictNullChecks": false, // temp "strictPropertyInitialization": false, // temp "noImplicitOverride": true, // "noPropertyAccessFromIndexSignature": true, From 9719a0ac43079a8f03b945ad764308f656204d77 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:38:08 -0800 Subject: [PATCH 07/11] MidiInput Nullish Handling --- editor/MidiInput.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/editor/MidiInput.ts b/editor/MidiInput.ts index 30dbf9f2..6de0475b 100644 --- a/editor/MidiInput.ts +++ b/editor/MidiInput.ts @@ -19,10 +19,6 @@ interface MIDIInput extends EventTarget { state: "disconnected" | "connected"; } -interface MIDIConnectionEvent { - port: MIDIInput; -} - interface MIDIMessageEvent { data: [type: number, key: number, velocity: number]; target: MIDIInput; @@ -64,6 +60,7 @@ export class MidiInputHandler { } private _handleStateChange = (event: MIDIConnectionEvent) => { + if (!event.port) return; if (event.port.type !== "input") return; switch (event.port.state) { From 6cafc0e57077fb8917bf211d12ec5121dc83750b Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:43:56 -0800 Subject: [PATCH 08/11] Unreachable Code Check --- editor/EasyPointers.ts | 12 ++++++------ synth/synth.ts | 2 +- tsconfig.json | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/editor/EasyPointers.ts b/editor/EasyPointers.ts index 2ddb544a..b397e272 100644 --- a/editor/EasyPointers.ts +++ b/editor/EasyPointers.ts @@ -1485,13 +1485,13 @@ export function getElementDimensions(element: HTMLElement, elementBox: `${Elemen switch (elementBox) { case ElementBox.borderBox: { return {width: element.offsetWidth, height: element.offsetHeight}; - } break; + } case ElementBox.insideBorder: { return { width: element.offsetWidth - parseFloat(styles.borderLeft) - parseFloat(styles.borderRight), height: element.offsetHeight - parseFloat(styles.borderTop) - parseFloat(styles.borderBottom), }; - } break; + } case ElementBox.paddingBox: { if (styles.display == "inline") { // For inline elements, the reported scrollWidth and scrollHeight are always zero even if there's a border. @@ -1502,7 +1502,7 @@ export function getElementDimensions(element: HTMLElement, elementBox: `${Elemen } else { return {width: element.scrollWidth, height: element.scrollHeight}; } - } break; + } case ElementBox.contentBox: { if (styles.display == "inline") { return { @@ -1515,7 +1515,7 @@ export function getElementDimensions(element: HTMLElement, elementBox: `${Elemen height: element.scrollHeight - parseFloat(styles.paddingTop) - parseFloat(styles.paddingBottom), }; } - } break; + } case ElementBox.imagePixels: { if (element instanceof HTMLImageElement) { return {width: element.naturalWidth, height: element.naturalHeight}; @@ -1524,10 +1524,10 @@ export function getElementDimensions(element: HTMLElement, elementBox: `${Elemen } else { throw new Error("EasyPointers: Unsupported element type for image box: " + element.tagName); } - } break; + } case ElementBox.svgTransform: { throw new Error("EasyPointers: svgTransform unsupported for HTML elements."); - }// break; // unreachable code because of the throw. + } default: throw new Error("EasyPointers: Unrecognized element box: " + elementBox); } } diff --git a/synth/synth.ts b/synth/synth.ts index 163f2cc2..cb3f741a 100644 --- a/synth/synth.ts +++ b/synth/synth.ts @@ -3240,7 +3240,7 @@ export class Song { } break; default: { throw new Error("Unrecognized song tag code " + String.fromCharCode(command) + " at index " + (charIndex - 1)); - } break; + } } } diff --git a/tsconfig.json b/tsconfig.json index 076b4a52..b3966b35 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,12 +6,11 @@ "noEmit": true, "skipLibCheck": true, // temp "strict": true, - // "strictNullChecks": false, // temp "strictPropertyInitialization": false, // temp "noImplicitOverride": true, // "noPropertyAccessFromIndexSignature": true, // "noUncheckedIndexedAccess": true, - // "allowUnreachableCode": false, + "allowUnreachableCode": false, "noUnusedLocals": true, "allowUnusedLabels": false, // "noUnusedParameters": true From 62c7aa95404b9c50b601e199673bc44792ad0a06 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:53:02 -0800 Subject: [PATCH 09/11] Isolated Modules Allows for compilation without needing to use ts, having incremental compilation (I think that's the name?) works when you mark types as types when exported from a module. --- editor/index.ts | 4 ++-- player/index.ts | 2 +- synth/synth.ts | 10 +++++----- tsconfig.json | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/editor/index.ts b/editor/index.ts index 0ce42ee4..39505fdd 100644 --- a/editor/index.ts +++ b/editor/index.ts @@ -1,11 +1,11 @@ // Copyright (c) John Nesky and contributing authors, distributed under the MIT license, see accompanying the LICENSE.md file. -export {Dictionary, DictionaryArray, EnvelopeType, InstrumentType, Transition, Chord, Envelope, Config} from "../synth/SynthConfig.js"; +export {type Dictionary, type DictionaryArray, EnvelopeType, InstrumentType, type Transition, type Chord, type Envelope, Config} from "../synth/SynthConfig.js"; export {EditorConfig} from "./EditorConfig.js"; export {ColorConfig} from "./ColorConfig.js"; import "./style.js"; // Import for the side effects, there's no exports. export {SongEditor} from "./SongEditor.js"; -export {NotePin, Note, Pattern, Instrument, Channel, Song, Synth} from "../synth/synth.js"; +export {type NotePin, Note, Pattern, Instrument, Channel, Song, Synth} from "../synth/synth.js"; export {SongDocument} from "./SongDocument.js"; export {ExportPrompt} from "./ExportPrompt.js"; export {ChangePreset} from "./changes.js"; diff --git a/player/index.ts b/player/index.ts index 1ad26ea7..d89f7438 100644 --- a/player/index.ts +++ b/player/index.ts @@ -588,4 +588,4 @@ renderZoomIcon(); renderPlayButton(); // When compiling synth.ts as a standalone module named "beepbox", expose these classes as members to JavaScript: -export {Dictionary, DictionaryArray, EnvelopeType, InstrumentType, Transition, Chord, Envelope, Config, NotePin, Note, Pattern, Instrument, Channel, Synth}; +export {type Dictionary, type DictionaryArray, EnvelopeType, InstrumentType, type Transition, type Chord, type Envelope, Config, type NotePin, Note, Pattern, Instrument, Channel, Synth}; diff --git a/synth/synth.ts b/synth/synth.ts index cb3f741a..4ae59321 100644 --- a/synth/synth.ts +++ b/synth/synth.ts @@ -7801,14 +7801,14 @@ export class Synth { // When compiling synth.ts as a standalone module named "beepbox", expose these imported classes as members to JavaScript: export { - Dictionary, - DictionaryArray, + type Dictionary, + type DictionaryArray, FilterType, EnvelopeType, InstrumentType, - Transition, - Chord, - Envelope, + type Transition, + type Chord, + type Envelope, Config, fastFourierTransform, forwardRealFourierTransform, diff --git a/tsconfig.json b/tsconfig.json index b3966b35..e32d4cfd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "NodeNext", "target": "ESNext", - // "isolatedModules": true, + "isolatedModules": true, "noEmit": true, "skipLibCheck": true, // temp "strict": true, From af4273a5b5c231ed10383fc637b6eef13f05ba7f Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:55:37 -0800 Subject: [PATCH 10/11] noPropertyAccessFromIndexSignature --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index e32d4cfd..573b55cf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "strict": true, "strictPropertyInitialization": false, // temp "noImplicitOverride": true, - // "noPropertyAccessFromIndexSignature": true, + "noPropertyAccessFromIndexSignature": true, // "noUncheckedIndexedAccess": true, "allowUnreachableCode": false, "noUnusedLocals": true, From 740d43c871d8ae3e34c8f8fa8b699eb70afddc91 Mon Sep 17 00:00:00 2001 From: Offroaders123 <65947371+Offroaders123@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:11:28 -0800 Subject: [PATCH 11/11] Oversight-related flags Some of the more strict TSConfig flags would require intent oversight, as it would change concepts of how the code functions, which I don't want to mangle with specifically. And I don't want to introduce a whole large list of sweeping changes either. --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 573b55cf..68bc09d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,10 +9,10 @@ "strictPropertyInitialization": false, // temp "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, - // "noUncheckedIndexedAccess": true, + // "noUncheckedIndexedAccess": true, // needs oversight to enable "allowUnreachableCode": false, "noUnusedLocals": true, "allowUnusedLabels": false, - // "noUnusedParameters": true + // "noUnusedParameters": true // needs oversight to enable } }