0

Is there a best way to check an object against a typescript infterface?

I am working between two schemas, where one extends the other. I need to convert the extension back to base, and am doing so by deleting props from the extension to shape it to the original base class. An example:

interface Base {
  prop1: string
  prop2?: string
  prop3?: string
}

interface Extended extends Base {
  prop4: string
  prop5: string
}

So in order to get Extended back to Base, I need to delete props prop4 and prop5

This is of course easy enough to do, but, I need to ensure that the final result conforms to the Base class, since deleting props does not tell the compiler anything, and the extension will pass the Base type check.

I have looked at using a type guard, and other alternatives, however, I have not found a way to do this which accommodates for the optional properties found in Base, or a seemingly efficient way to do it.

Here is a basic plan for the type guard as well as handling optional props:

function isBase(arg: any): arg is Base {
  return arg
    && arg.prop1
    && (arg.prop2 || true)
    && (arg.prop3 || true)
}

Besides being a lot of work for a lot of props, it's brittle. Soon as Base changes, this technique no longer works as intended. I feel like there is (should be) some Typescript way via utility types that could check the props against the Base interface, so it will always work as intended.

Update

I found this. Looks very close but could not get it working with interfaces.

skwny
  • 2,930
  • 4
  • 25
  • 45
  • Utility types wouldn't work since interface are design-time types and not run-time types, therefore you'd need to have type-guard code compiled in the first place, which will then run. Type guards are the only solution AFAIK. – Amit Beckenstein Sep 09 '19 at 21:02
  • "I need to convert the extension back to base" Why? If the type extends a base then that type can be treated as a base, you don't need to remove properties... – Gerrit0 Sep 09 '19 at 21:43
  • The extension is used for client side purposes, and the base is what is stored in the db. So while it can be treated as the base, I do not want to store the additional data the extension holds (in the db), and want to check that is the case before sending it across the wire. – skwny Sep 09 '19 at 21:57

1 Answers1

1

If you need to keep Base as a standalone property, using composition instead of inheritance might be a better approach, for instance:

interface Base {
  prop1: string
  prop2?: string
  prop3?: string
}

interface Extended {
  data: Base
  prop4: string
  prop5: string
}

Do whatever is needed with Extended but only send data to database.

Psidom
  • 209,562
  • 33
  • 339
  • 356
  • This looks like a good technique. Although that means all uses of `Extended` class would need to be updated to have the `data` prop that consists of `Base`. – skwny Sep 10 '19 at 02:01