typescript-is icon indicating copy to clipboard operation
typescript-is copied to clipboard

Feature: createEqualizerType() which works exactly as createAssertType(), but removes the props missing in the type

Open dko-slapdash opened this issue 4 years ago • 3 comments

Just a thought: createAssertType() works perfectly, and we use it for more and more external API calls now (we have hundreds of them). But the lambda which it creates just verifies the structure of the object, it doesn't remove the fields which are not mentioned in the typing. E.g. if we do

createAssertType<{ a: string }>()({ a: "a", b: "b" })

then the returned object is { a: "a", b: "b" } and not { a: "a" }.

Would be cool to have another method (say, createEqualizerType or createFilterType or createSanitizeType) which does that: validation + filtering.

dko-slapdash avatar Apr 20 '20 01:04 dko-slapdash

Hmm the existing equality function family (equals, createEquals, assertEquals, createAssertEquals) does something similar, but it performs validation only, and does not filter out properties that don't belong there. For example it will throw an error: createAssertEquals<{ a: string }>()({ a: "a", b: "b" }) because property b is superfluous. But it won't change the object to take out b.

To make this happen will take some effort so I'll consider it out of scope for now. However I'll accept a PR if you can make it happen :)

woutervh- avatar May 07 '20 16:05 woutervh-

I second this, having filtering ability would be awesome (we generate our route handlers and use assertEquals to ensure request parameters are always correct). For production use, filtering out unwanted properties is often favourable so that we do not accidentally show the user a cryptic validation error message.

Happy to give this a go, haven't gone through the code at all but I assume it shouldn't be a huge change from validation.

francescov1 avatar Dec 30 '20 02:12 francescov1

Checking in if there's any progress/updates on this? If you can point me in the right direction I'd love to help out over the next month or two.

As a workaround (only really works for top-level properties but let me know if you have ideas for nested) we've used ts-transformer-keys & _.pick to first filter an object and then run it through assertType:

import { keys } from "ts-transformer-keys";
import _ from "lodash"
import { assertType } from "typescript-is";

interface  FilteredObject {
  a: string
}

const objectNeedingFiltering = { a: "a", b: "b" }
const filteredObject = _.pick(objectNeedingFiltering, keys<FilteredObject>())

// now passes validation
assertType<FilteredObject>(filteredObject);

As mentioned, this does not support nested objects but still comes in handy. Maybe there's potential to use a similar strategy for integration this feature into typescript-is?

francescov1 avatar Mar 23 '21 15:03 francescov1