0

I'm getting some data that has a metadata field in it that I'd like stripped out. It comes to me in typed variables like so:

type MainRecord = {
  id: string
  fieldOne: string
  related: RelatedRecord[]
  __typename: string
}

type RelatedRecord = {
  id: string
  fieldTwo: string
  __typename: string
}

I'm using Formik to update the records but I don't want the __typename fields included when I create the initial values for the form because trying to send the data to the server with the metadata included causes syntax errors for the query when I do. I have separate types for the Formik forms like so:

type MainFields = {
  id: string
  fieldOne: string
  related: RelatedFields[]
}

type RelatedFields = {
  id: string
  fieldTwo: string
}

My solution was to try to cast the MainRecord data as a MainFields object which seems like its working because fields.__typename is not a valid property and neither is fields.related[0].__typename.

const record: MainRecord = {
  id: "10",
  fieldOne: "Foo",
  __typename: "Main",
  related: [
    {
      id: "20",
      fieldTwo: "Bar",
      __typename: "Related"
    },
    {
      id: "21",
      fieldTwo: "Baz",
      __typename: "Related"
    },
  ]
}

const fields: MainFields = record // or "as MainFields"

However when you log the fields variable, the metadata is still there and it shouldn't be.

console.log("fields: ", fields);

I guess I could strip them out programmatically by hand but there's got to be a better way. Any ideas? I'm sure there's a typescript way of accomplishing this but I just don't know it.

aarona
  • 35,986
  • 41
  • 138
  • 186
  • https://medium.com/poka-techblog/simplify-your-javascript-use-map-reduce-and-filter-bd02c593cc2d - either filter or map or chain the two. – JGFMK Aug 30 '20 at 07:03

2 Answers2

1

I don't think TypeScript will actually mutate whenever you use the as keyword, it will just treat it "as" the appropriate type in an "if you say so" type manner.

Your best bet really is to do a filter on the properties either with your own utility or something like lodash.

Removing object properties with Lodash

See this question which seems to be considering something similar.

Remove properties from an object that are not declared in a type interface

zero298
  • 25,467
  • 10
  • 75
  • 100
  • I've heard of lodash. I'll look into that. If you have a quick solution to fix this with lodash, please add it to your answer and I will mark it as the accepted answer. – aarona Aug 29 '20 at 23:57
0

Using lodash's omit function, I found a way to do a recursive omit like so:

function omitDeep(obj: any, keyToOmit: string) {
  _.forIn(obj, function (value, key) {
    if (_.isObject(value)) {
      omitDeep(value, keyToOmit);
    } else if (key === keyToOmit) {
          delete obj[key];
    }
  });
}
```js
aarona
  • 35,986
  • 41
  • 138
  • 186
  • Remember that you can do this easily today using the spread operator, as in `const { [keyToOmit]: _, ...rest } = obj`, where obj is the original value, keyToOmit is the property to "remove", _ is a variable name which is used as a discard, and ...rest is the remaining properties which can be used afterwards. (Although this is just one level deep) – Patrick Sep 02 '20 at 00:13
  • Yeah I needed a solution that was more substantial which would be recursive. I actually tried a solution like this and it was going to be way more involved than I wanted. Spread operator is a good solution for something simple though, I agree. – aarona Sep 02 '20 at 17:22