Can data be filtered based on type definitions using Runtime APIs and TypeDefs?

My theory: Is it feasible to generate a guard from TypeDefs that will be present at runtime? I recall hearing that this is achievable with TS4+.

Essentially, two issues; one potentially resolvable:

  1. If your API (which you can't control) provides noisy data and you need to filter them based on existing type definitions, what approach would you take?

  2. At times, your type definitions may appear unconventional, making it challenging to filter by lodash.keyBy as the iteratee could vary in shape depending on the given TypeDefs.

For instance:

You have an object type defined as follows:

type ObjectType = {
  [key: string]: {
    foo?: string | number;
  };
};

The following data would pass based on the above ObjectType:

const someOKCollection: Array<ObjectType> = [
  { june: { foo: 1 } },
  { earth: {} },
  { milky: { foo: "Hi" } }
];

Imagine this data is received from an API:

const collectionFromApi: Array<unknown> = [
  { car: { foo: 1 } },
  { soup: {} },
  { water: { foo: "Hi" } },
  { sun: { bar: "Hi" } }
];

In this scenario, the entry for sun is unnecessary due to the ObjectType (as it contains bar). The challenge lies in transforming the data into:

const desiredResult = {
  noMatter: { foo: 1 },
  what: {},
  Ever: { foo: "Hi" }
};

Main Question:

Ignoring the solvability of the first question, how should the iteratee be automatically crafted from the TypeDefinition so that utilizing lodash.keyBy or other collection functions results in the desired outcome?

UPDATE: Explore a simplified CodeSandBox here: https://codesandbox.io/s/typescript-lodash-types-6844w0?file=/src/index.type.ts (please note: root key names may differ at runtime; only TypeDefs must be adhered to)

Answer №1

When not using lodash:

Check out this example on CodeSandbox

// import keyBy from "lodash/fp/keyBy";

type ObjectType = {
  [key: string]: {
    foo?: string | number;
  };
};

// const someOKCollection: Array<ObjectType> = [
//   { a: { foo: 1 } },
//   { b: {} },
//   { c: { foo: "Hi" } }
// ];

const collectionFromApi: unknown[] = [
  { a: { foo: 1 } },
  { b: {} },
  { c: { foo: "Hi" } },
  { d: { bar: "Hi" } }
];

type AllowedKey = "a" | "b" | "c";
const allowedKeys = new Set<AllowedKey>(["a", "b", "c"]);

// const desiredResult = {
//   a: { foo: 1 },
//   b: {},
//   c: { foo: "Hi" }
// };

type Result = {
  [key in AllowedKey]: { foo?: string | number };
};

const y = collectionFromApi.reduce<Result>((acc, val) => {
  if (typeof val !== "object" || val === null) return acc;

  const key = Object.keys(val)[0];

  if (
    key === undefined ||
    !allowedKeys.has(key as AllowedKey)
  ) {
    return acc;
  }

  acc[key as AllowedKey] = (val as Result)[key as AllowedKey];
  return acc;

}, {} as Result);
console.log("Y", y);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

TypeScript PatchBaseline with AWS CDK

I am currently working with the AWS CDK and TypeScript, utilizing the @aws-cdk/aws-ssm library to create a PatchBaseline. While I have successfully created the Patch baseline, I'm encountering difficulties when attempting to define approvalRules. I ca ...

How to efficiently store and manage a many-to-many relationship in PostgreSQL with TypeORM

I have a products entity defined as follows: @Entity('products') export class productsEntity extends BaseEntity{ @PrimaryGeneratedColumn() id: number; //..columns @ManyToMany( type => Categories, categoryEntity => cat ...

What causes *ngIf to display blank boxes and what is the solution to resolve this problem?

I am currently working on an HTML project where I need to display objects from an array using Angular. My goal is to only show the objects in the array that are not empty. While I have managed to hide the content of empty objects, the boxes holding this co ...

Evolution of ReactJS state over time

When working with React, I wanted to increment a state variable called progressValue by 0.1 every 500 ms until it reaches 100. Here's what I initially tried: const [progressValue, setProgressValue] = React.useState<number>(0) const tick ...

Is there a way to efficiently compare multiple arrays in Typescript and Angular?

I am faced with a scenario where I have 4 separate arrays and need to identify if any item appears in more than two of the arrays. If this is the case, I must delete the duplicate items from all arrays except one based on a specific property. let arrayA = ...

What is the proper way to display the date and time 2021-11-14T18:30:00.000+00:00?

Here is my ts file code: mydate: Date = new Date('2021-11-14T18:30:00.000+00:00'); However, I want the date to be in this format:- 07-July-2022 If anyone can assist with achieving this format, it would be greatly appreciated. Thank you! ...

The replacer argument of the JSON.stringify method doesn't seem to work properly when dealing with nested objects

My dilemma is sending a simplified version of an object to the server. { "fullName": "Don Corleone", "actor": { "actorId": 2, "name": "Marlon", "surname": "Brando", "description": "Marlon Brando is widely considered the greatest movie actor of a ...

Unable to resolve the Typescript module within a different file

I am in the process of transitioning my React app to TypeScript. Currently, everything is working fine. However, I encountered an issue after adding the TypeScript compiler and renaming files to .ts and .tsx extensions - it is now throwing a "module not fo ...

For each array element that is pushed, create and return an empty object

I am encountering an issue with an array where the objects are being generated by a push operation within a function. Despite successfully viewing the objects directly in the array, when I attempt to use forEach to count how many times each id uses the ser ...

What is the process for refreshing the dropdown menu in angular2 after modifying the data in the typescript file?

Right now, I am implementing angular2 in my project. I have a dropdown component labeled as CFC Filter {{val}} In the typescript file, I have defined this.filters = ["0", "60", "100", "180", "600", "1000"]; If the filter value retrieved from the da ...

The data type returned by a method is determined by the optional parameter specified in the

I have a situation where I need to create a class with a constructor: class Sample<T> { constructor(private item: T, private list?: T[]) {} } and now I want to add a method called some that should return: Promise<T> if the parameter list ...

The return type of Array.find is accurate, however, it contains an error

Trying to find a way to indicate the expected return type of Array.find() in TypeScript, I encountered an incompatibility warning. View code in playground class A { "type"="A" t: string; #a = 0 constructor(t: string) { ...

Show a few values as a string in Angular using Typescript

I am working with JSON data and I want to know how to display hobbies without including the word "all" in an Angular/TypeScript application. { "Name": "Mustermann1", "Vorname": "Max1", "maennlich& ...

The property 'x' is not found on 'Reel' type in this context

Creating a custom class extending Container in PIXI.js: export class CustomContainer extends Container { constructor(width: number, height: number) { super(); var sprite: Sprite = Sprite.fromImage("assets/images/elephant.png"); ...

Tips for minimizing delay after user input with Material UI

Background I'm currently working on a website project that includes a carousel of MUI cards using a unique stack as the underlying component. However, I've encountered an issue where there is a noticeable 4-second delay whenever I try to scroll ...

Tips for inserting an HTML element within an exported constant

I need help formatting an email hyperlink within a big block of text. Here is the code snippet: const myEmail = '<a href="mailto:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2e4b564f435e424b6e4b564f435e424b004d41 ...

"Alert in Javascript executing prematurely prior to initiating the function for sending a get request

private validateURL(url: string) { let isValid = false; this.$http.get(url).then( (data) => { console.log('success'); isValid = true; } ).catch( (reason) => { console. ...

"Efficient ways to calculate the total sum of an array of objects based on a specific property

I currently have a straightforward method that calculates the total sum of an object array based on one of the properties. const calculateSum = <T extends object, K extends keyof T>(array: T[], property : K) : number =>{ let total = 0; if ( ...

Encountering a sign-in issue with credentials in next-auth. The credential authorization process is resulting in a

I am currently facing an issue with deploying my Next.js project on Vercel. While the login functionality works perfectly in a development environment, I encounter difficulties when trying to sign in with credentials in Production, receiving a 401 error st ...

Utilizing an AwsCustomResource in AWS CDK to access JSON values from a parameter store

I found a solution on Stack Overflow to access configurations stored in an AWS parameter. The implementation involves using the code snippet below: export class SSMParameterReader extends AwsCustomResource { constructor(scope: Construct, name: string, pr ...