Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: Filter Object by Interface or Class

I would like to sync an object that is provided by an API to a table. The table is defined in Sequelize and has an interface and a class:

declare interface SampleInterface {
  value1?: string;
  value2?: string;
  value3?: number;
}
class SampleClass implements SampleInterface {
  value1?: string;
  value2?: string;
  value3?: number;
}

The response of the API is not always the same, but could look something like this:

const sampleResponse = {
  value2: "..."
  value3: 0
  value4: "..."
}

Now, I would only like create a new object that can be passed to sequelize that has the matching contents, for example:

const filteredResponse = {
  value2: "..."
  value3: 0
}

How can I match the object properties keys to the interface or class?

Thanks!

like image 310
lucbas Avatar asked Oct 26 '25 08:10

lucbas


1 Answers

If I understand you right, you:

Have: API which produces not 100% predictable response.

Want: to create a concrete instance of the class from this untrusted source

If I am right you have two options:

If input object is not very big and dynamic you could do everything explicitly:

const unreliableObject = fetchFromApi();
const result = new Result();

if (typeof unreliableObject.name  === 'string') {
    result.name = unreliableObject.name;
}

This code is more-less OK except it is toooo verbose.

As a bit more advanced solution, you can create TransformationMapper, something like this:

class MyClass {
    name: string;
}

const expectedKeys: (keyof MyClass)[] = ['name'];
const data: any = { v: 1, name: '13212' };

const res = expectedKeys.reduce((result, fieldName) => {

    const value = data[fieldName];
    if (value != null) {
        result[fieldName] = data[fieldName]
    }

    return result;
}, new MyClass());

console.log(res);

UPDATE

Is there any way, I could the get keyof MyClass programmatically

The main idea is to get a scheme to parse the original response. Luckily, you already got it.

So you need to: create an instance of the desired class, and get keys from it:

This can be done using:

Object.keys()

Object.entries()

const data: any = {};

let result = new MyClass();
result = Object.keys(result).reduce((result, fieldName) => {

    const value = data[fieldName];
    if (value != null) {
        result[fieldName] = data[fieldName]
    }

    return result;
}, result)

But I also have to warn you. If you don't trust API, you should not only parse, but also validate values you are parsing. In another case, incorrect types provided via API may break your app.

You can write your own validation (it is not that hard) or take something existing like yup

like image 89
Drag13 Avatar answered Oct 28 '25 22:10

Drag13