Transforming API data into a particular type using Typescript

I am looking to extract only specific properties from a given object. Can TypeScript interfaces be used to iterate through the data and eliminate unnecessary properties?

Sample data:

[
  0: {
    "original_language" : "en",
    "title" : "The First Title",
    "original_title" : "The First Original Title",
    "overview": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac suscipit nulla.",
    "release_date": "2022-05-04",
    "popularity": 9411.64
  },
  1: {
    "original_language" : "en",
    "title" : "The Second Title",
    "original_title" : "The Second Original Title",
    "overview": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac suscipit nulla.",
    "release_date": "2022-05-04",
    "popularity": 9411.64
  },
  2: {
    "original_language" : "es",
    "title" : "The Third Title",
    "original_title" : "The Third Original Title",
    "overview": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac suscipit nulla.",
    "release_date": "2022-05-04",
    "popularity": 9411.64
  }
]

Desired object properties (Typescript Interface):

interface IMovie {
  overview: string,
  release_date: Date,
  title: string
}

My attempt at creating a mapper function:

const movieMapper = (movies: []): [IMovie] => {
  return movies.map(movie => <IMovie>movie);
}

Answer №1

Two interfaces can be created: one for the actual API response array items and one for desired items:

interface FullMovie {
  original_language: string
  title: string
  original_title: string
  overview: string
  release_date: Date
  popularity: number
}

type Movie = Pick<FullMovie, 'overview' | 'release_date', 'title'>

A separate type Movie can be defined, but it is recommended to make it dependent on the original interface so any changes in FullMovie will automatically reflect in Movie.

Mapping can then be performed as follows:

const movieMapper = (movies: FullMovie[]): Movie[] => {
  return movies.map(movie => ({
    overview: movie.overview,
    release_date: movie.release_date,
    title: movie.title,
  }));
}
// or, using destructuring
const movieMapper = (movies: FullMovie[]): Movie[] => {
  return movies.map(({ overview, release_date, title }) => ({ overview, release_date, title }));
}

Answer №2

Your function is expecting a tuple as the return type, not an array.

To solve this, you can utilize object destructuring to select specific fields and transform them into a new object.

const filmTransformer = (films: any[]): IFilm[] => {
    return films.map(({plot, releaseDate, title}) => ({ plot, releaseDate, title }));
}

console.log(filmTransformer(films))

Answer №3

If you utilize io-ts, you have the option to create a codec like this:

// Codec implementation
import * as t from 'io-ts'

export const movieCodec = t.type({
  overview: t.string,
  release_date: t.string, // consider using custom codecs for decoding dates into JS Date objects
  title: t.string,
})

export const movieListCodec = t.array(movieCodec)

After defining the codec, you can validate the response data against it.

// Handling the response in your application
fetch(someEndpoint)
  .then<unknown>(r => r.json())
  .then(movieCodecList.is)
  .then(verifiedResponse => {
    // verifiedResponse is not only correctly typed but also validated at runtime
  })

This explanation may go beyond your initial query, but it's worth noting that performing runtime checks on external data is strongly recommended!

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

Function for querying database is not executing in an asynchronous manner

After setting up a function in my node server to handle querying the database and returning results, I found that using async await could help streamline the process throughout my routes. This way, I wouldn't end up with nested queries within one anot ...

Using Axios with Mongoose to Update Documents in Not Working State

I'm currently working on implementing an edit feature for updating posts. My goal is to initially update a specific post by its ID and then make it more dynamic. Although I am able to successfully send a PUT request using axios, I'm not getting ...

Remove any overlapping datetime values from a JavaScript array of objects

Is there a way to efficiently remove any overlaps between the start and end times (moment.js) in a given array of objects? [{ start: moment("2019-03-23T15:55:00.000"), end: moment("2019-03-23T16:55:00.000")}, { start: moment("2019-03-23T14:40:00.000"), e ...

Validating Two DateTime Pickers as a Group with Javascript in asp.net

How to Ensure Group Validation of Two DateTime Pickers Using JavaScript in ASP.NET ...

<use> - SVG: Circles with different stroke properties

Why is the stroke of both <use> elements being ignored here? The stroke color of <circle> is set to blue, which is also appearing on both <use> elements. Why? I am trying to set different stroke colors for all three of these elements, bu ...

Error: Unable to access the 'create' property of an undefined object while utilizing sequelize to register a user and add an entry

Whenever I try to execute this controller, an issue arises indicating a problem with the recognition of the .create method from the model. What is the correct way to import Sequelize in order to utilize it effectively? const db = require("../Models/m_use ...

looking to display the latest status value in a separate component

I am interested in monitoring when a mutation is called and updates a status. I have created a component that displays the count of database table rows when an API call is made. Below is the store I have implemented: const state = { opportunity: "" } ...

Unable to establish a connection with the endpoint

I'm encountering an issue while trying to connect to the endpoint on the server. Below is the code snippet: Register.jsx function Register() { const [registerUser, setRegisterUser] = useState({ username: "", email: "", password: "", ...

Is it necessary to exclude the 'scripts' folder from your Aurelia project's .gitignore file?

Should I exclude the 'scripts' directory that Aurelia is building to in my CLI project from Git by adding it to .gitignore, or is there a specific purpose for tracking changes to this directory? ...

Instructions on how to activate scrolling for a div element that becomes visible upon clicking a button

When a button in the navbar is clicked, a div appears with a height that exceeds the viewport/page size. How can I enable scrolling for the entire page when this happens? I attempted to use overflow: scroll, but it only applied scrolling to the internal d ...

What is the reason for the value of an object's key becoming undefined when it is set within a loop?

I've always wondered why setting a certain object's key as its own value in a loop results in undefined. Take this code block, for example: var text = 'this is my example text', obj = {}, words = text.split(' '); for (i = ...

Enhance Component Reusability in React by Utilizing Typescript

As I embark on developing a React application, my primary goal is to keep my code DRY. This project marks my first experience with Typescript, and I am grappling with the challenge of ensuring reusability in my components where JSX remains consistent acros ...

Ensure the CSS class stays on Quill clipboard.dangerouslyPasteHTML

One of the challenges I face with using the Quill Text Editor is that when I use the method clipboard.dangerouslyPasteHTML to paste HTML into the editor, it does not maintain custom CSS classes. For example: let content= '<p class="perso-clas ...

Ways to retrieve a specific attribute within a detailed JSON reply

I have implemented cloud code in ParseServer - Back4app, which utilizes node.js to send a request for Football API. The axios request returned the following result: { "result": { "get": "teams", "param ...

Sharing a state object with another React file can be accomplished by using props or context to

My first React file makes an API call to retrieve data and save it in the state as Data. import React, { Component } from "react"; import axios from "axios"; import Layout from "./Layout"; class Db extends Component { constructor() { super(); th ...

Is there a way to identify a change in the URL using JQuery?

My goal is to clear the localStorage when a user navigates to a different page. For instance, if I am currently on . When the user goes to the URL, , I want to clear the localStorage. This is my script using JQuery. $(window).unload(function(){ if ...

Is it possible to include two of these on a single page with unique variables? (Using JQuery)

I am looking to create two similar pages, each with different percentages. However, when I try modifying the JS or changing class/ID names, it keeps pulling data from the first SPAN element. http://jsfiddle.net/K62Ra/ <div class="container"> <di ...

Executing PHP include statement with ajax: A step-by-step guide

I am trying to achieve a feature on my website where when a button is clicked in the index.php file, an AJAX request will load about.php and display it inside a div tag within index.php. Unfortunately, my current code doesn't seem to be working as exp ...

Dealing with the challenge of managing multiple instances in a setup involving Ajax long polling (comet) and PHP on Lighttpd v1

I am a newcomer to this platform, so I hope to provide all the necessary details about my question. I have been attempting to set up a mechanism for "new message arrived notification" using long polling. Currently, I am triggering the polling request thro ...

Converting data into a multidimensional array in AngularJS: A comprehensive guide

Struggling to convert a JSON array into a multidimensional array, looking for some guidance. I attempted using _.groupBy in underscore.js, but it's not proving successful with the nested array. If there is any way to convert from the given data [{ ...