error TS18048: 'note' is possibly 'undefined'. is reported when a variable, parameter or property whose type includes undefined is used as if it were always set. It is the named form of TS2532.
In JSDoc, an optional parameter (@param {string} [note]) and an optional property ({ discount?: number }) both include undefined, which is the point of marking them optional: the code using them has to handle the case where they are left out.
At a glance
| Code | TS18048 |
|---|---|
| Message | '{0}' is possibly 'undefined'. |
| TypeScript's category | error |
| Listed under | Null, undefined and unknown |
| Turned on by | strictNullChecks, strict |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} is filled in by tsc for each error.
What it looks like
/** @typedef {{ sku: string, name: string, price: number }} Product */
/** @type {Product[]} */
const products = [{ sku: "TEE-01", name: "Cotton tee", price: 19 }];
/** @param {string} sku */
export function priceOf(sku) {
const product = products.find((p) => p.sku === sku);
return product.price;error TS18048: 'product' is possibly 'undefined'.
}
/** @param {string} [note] */
export function giftNote(note) {
return note.trim();error TS18048: 'note' is possibly 'undefined'.
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- The variable holds a result that may be
undefined(find,Map.get, an optional property). - A parameter is marked optional in its
@paramtag, or hasundefinedin its type, and is used without a default or a check. strictNullChecks(part ofstrict) is on.
How to fix it
Check it, or give it a default
if (product === undefined) return 0; narrows the variable for the lines after it. For a parameter, a default value (note = "") removes undefined from its type inside the function while callers may still leave it out.
/** @typedef {{ sku: string, name: string, price: number }} Product */
/** @type {Product[]} */
const products = [{ sku: "TEE-01", name: "Cotton tee", price: 19 }];
/** @param {string} sku */
export function priceOf(sku) {
const product = products.find((p) => p.sku === sku);
if (product === undefined) return 0;
return product.price;
}
/** @param {string} [note] */
export function giftNote(note = "") {
return note.trim();
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Or make it required
If every caller passes the value, the brackets in @param {string} [note] are wrong: remove them, and calls that leave the argument out are reported instead.
Gotchas
- Truthiness checks (
if (note)) also skip the empty string and0. Compare withundefinedwhen those values are valid. exactOptionalPropertyTypeschanges how optional properties treat an explicitundefined, not whether they need a check.
Sources
- Everyday Types: the null and undefined section · TypeScript handbook
- JSDoc Reference: @param and @returns · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.