Home > Blockchain >  How should I work with empty objects' types?
How should I work with empty objects' types?

Time:11-04

I have a value that's either {}, or an object with 30 fields. ESLint suggests that a reasonable type for the former case is Record<string, never>, so the compound type looks like Record<string, never> | MyBigObjectType.

I'm trying to discriminate between the two cases using the presence or absence of a field Foo. Unfortunately, I can't use "Foo" in val or !!val.Foo because the type checker supposes that it could be present in Record<string, never>. But it can't! That's the whole purpose of never!

How do I accomplish this without type casts?

CodePudding user response:

If you use Record<never, never> as the empty object type then you can use "Foo" in val to discriminate.

CodePudding user response:

You haven't shared how you're creating or using these objects, but if using an assertion (cast) is specifically the problem, you can use a function returning a type predicate for compile-time and runtime safety.

TS Playground link

// "an object with 30 fields"
type MyBigObjectType = {
  foo: string;
  bar: number;
  // etc...
};

function isMyObject (value: object): value is MyBigObjectType {
  // checking specified size of keys and presence of 'foo' property,
  // but you can modify to fit your requirements
  return Object.keys(value).length === 30 && 'foo' in value;
}

function fn (value: MyBigObjectType): void {}

const o1 = {};
fn(o1); // nope
if (isMyObject(o1)) fn(o1); // ok

declare const o2: object;
fn(o2); // nope
if (isMyObject(o2)) fn(o2); // ok

declare const o3: MyBigObjectType;
fn(o3); // ok
  • Related