DedSec Project

TS18048 — DedSec Project

TS18048 — possible undefined is a real missing-result branch Root cause TS18048 warns that a value is possibly undefined. Array.find returns the first matching element or undefined if there…

TS18048 — possible undefined is a real missing-result branch

Root cause

TS18048 warns that a value is possibly undefined. Array.find returns the first matching element or undefined if there is no match. Reading match.title immediately assumes all requested IDs exist, a premise that can fail on an empty array, a misspelled key, or a changed dataset.

Reliable fix

Check match === undefined before accessing its properties; TypeScript's control-flow analysis then narrows the type in the success branch. Throw a RangeError containing the missing ID rather than relying on a later TypeError. The test confirms the normal branch and an explicit absent-ID failure.

Verified TypeScript example

type RecordItem = {id: string; title: string};
function titleById(rows: RecordItem[], id: string): string {
  const match = rows.find((row) => row.id === id);
  if (match === undefined) throw new RangeError(`missing ID: ${id}`);
  return match.title;
}
if (titleById([{id: 'A', title: 'Intro'}], 'A') !== 'Intro') throw Error();
try { titleById([], 'B'); throw Error('accepted missing ID'); }
catch (err) { if (!(err instanceof RangeError)) throw err; }
console.log('PASS TS18048');

Why it works

Optional chaining is useful if a missing result is acceptable and the return type reflects undefined, but a mandatory title lookup should not silently return an empty string. The non-null assertion operator (match!) compiles away and does not protect runtime. Do not confuse undefined from a missing lookup with a record whose title is an empty string; those require distinct policies.

Reproduction and build commands

Save as main.ts and run tsc --strict --target es2022 --module commonjs --outDir dist main.ts && node dist/main.js. Reproduce TS18048 in a separate file with const match = rows.find(...); console.log(match.id); compiled under --strict and a recent TypeScript version.

Diagnostics to practice

Replace find with Map.get(id) and identify the same undefined possibility. Design a union such as {ok:true,value:...}|{ok:false,error:...} instead of exceptions, then verify that callers narrow on ok before using value.

Reference: https://www.typescriptlang.org/docs/handbook/2/narrowing.html