Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

194
Views
Typescript: type guard for whether an object property is defined, when the key is a wide type?

I have a function that returns whether an object property is undefined. I need this function instead of just doing obj[key] === undefined because otherwise I'd sometimes get Property 'foo' does not exist on type 'Bar'.. It's straightforward to write the type when the property key is a literal. I.e.:

function hasDefinedProp<
  Obj extends Partial<Record<string, any>>,
  Prop extends string,
>(
  obj: Obj,
  prop: Prop,
): obj is Obj & Record<Prop, Prop extends keyof Obj ? Exclude<Obj[Prop], undefined> : unknown> {
  return obj[prop] !== undefined;
}

const obj: Partial<Record<string, number>> = {};
if (hasDefinedProp(obj, 'foo')) {
    obj.foo + 1; // No error.
    obj.bar + 1; // "Object is possibly 'undefined'."
}

However, this doesn't work when the key's type is a wide type, i.e.:

const obj: Partial<Record<string, number>> = {};
const key: string = '';
if (hasDefinedProp(obj, key)) {
    obj[key] + 1; // No error.
    obj.bar + 1; // No error. Should be "Object is possibly 'undefined'."
}

Is it possible to make the type guard work for wide types?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

AFAIK, it is not possible. Once you have added explicit string type to const key: string = ''; - TS is unable to narrow literal type of key. As a result, you are allowed to use any string you want to access a property. TS is unable to distinguish two types with type string in this example:

const obj: Partial<Record<string, number>> = {};
const key: string = '';
if (hasDefinedProp(obj, key)) {
    obj[key] + 1; // No error.
    obj.bar + 1; // No error. Should be "Object is possibly 'undefined'."
}

This remind me an example with explicit type and immutable type assertion:

const record: Record<string, number> = {
    a: 1
} as const;

type Keys = keyof typeof record // string instead of "a"

It means that in this particular case it might be a good idea to forbid using wide types:

type ForbidWide<Prop> = Prop extends string ? string extends Prop ? never : Prop : never


function hasDefinedProp<
    Obj extends Partial<Record<string, any>>,
    Prop extends string,
    >(
        obj: Obj,
        prop: ForbidWide<Prop>,
): obj is Obj & Record<Prop, Prop extends keyof Obj ? Exclude<Obj[Prop], undefined> : unknown> {
    return obj[prop] !== undefined;
}


const obj: Partial<Record<string, number>> = {};
const key: string = '';
hasDefinedProp(obj, key) // error

Playground

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!