There is generic get method defined in axios/index.d.ts
get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
Example
interface User {
id: number;
firstName: string;
}
axios.get<User[]>('http://localhost:8080/admin/users')
.then(response => {
console.log(response.data);
setUserList( response.data );
});
I think you are passing list the wrong way to child component.
const [users, setUserList] = useState<User[]>([]);
<UserList items={users} />
interface UserListProps {
items: User[];
};
const UserList: React.FC<UserListProps> = ({items}) => {
return (
<Fragment>
<ul>
{items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
</li>
))}
</ul>
</Fragment>
);
};
Answer from Józef Podlecki on Stack Overflow
» npm install @types/axios
How to Type Axios.js 'AxiosResponse' data generic
How to use Axios with TypeScript when using response interceptors (AxiosResponse issue)
typescript - How to correctly use and install Axios - Stack Overflow
Typescript types do not make sense
Videos
There is generic get method defined in axios/index.d.ts
get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
Example
interface User {
id: number;
firstName: string;
}
axios.get<User[]>('http://localhost:8080/admin/users')
.then(response => {
console.log(response.data);
setUserList( response.data );
});
I think you are passing list the wrong way to child component.
const [users, setUserList] = useState<User[]>([]);
<UserList items={users} />
interface UserListProps {
items: User[];
};
const UserList: React.FC<UserListProps> = ({items}) => {
return (
<Fragment>
<ul>
{items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
</li>
))}
</ul>
</Fragment>
);
};
You need to provide a type argument when calling axios.get if you do not want Axios to infer the type for the value response as any.
And you are passing an incorrect type argument when you useState to create the array of users.
The correct way
interface User {
id: number;
firstName: string;
}
// Initialized as an empty array
const [users, setUserList] = useState<User[]>([]); // 'users' will be an array of users
For example,
import React, {useEffect, useState, Fragment } from 'react';
import UserList from './UserList';
import axios from 'axios';
interface User {
id: number;
firstName: string;
}
// You can export the type TUserList to use as -
// props type in your `UserList` component
export type TUserList = User[]
const Users: React.FC = (props) => {
// You can also use User[] as a type argument
const [users, setUserList] = useState<TUserList>();
useEffect(() => {
// Use [] as a second argument in useEffect for not rendering each time
axios.get<TUserList>('http://localhost:8080/admin/users')
.then((response) => {
console.log(response.data);
setUserList(response.data);
});
}, []);
return (
<Fragment>
<UserList {...users} />
</Fragment>
);
};
export default Users;
If you choose to export the type type TUserList = User[], you can use it in your UserList component as the type for props. For example,
import React, {Fragment } from 'react';
import { TUserList } from './Users';
interface UserListProps {
items: TUserList // Don't have to redeclare the object again
};
const UserList: React.FC<UserListProps> = (props) => {
return (
<Fragment>
<ul>
{props.items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
{ /* Do not call the delete function. Just point
to it. Set this to null in bind(). */}
</li>
))}
</ul>
</Fragment>
);
};
export default UserList;
Hi all!
I'm using the axios http library for Node to make requests to a public API as follows:
const response = await axios.get(url) logPaginatedResponse(response)
After receiving a response and storing it in the response variable above, I am passing the variable to the logPaginatedResponse function to log the response to the console.
My logPaginatedResponse function looks like this:
import { AxiosResponse } from "axios"
export const logPaginatedResponse = async (response: AxiosResponse) => {
console.dir({
total_records: response.data.meta.pagination.total,
records_per_page: response.data.meta.pagination.per_page,
current_page: response.data.meta.pagination.current_page,
total_pages: response.data.meta.pagination.total_pages,
})
}
The AxiosResponse interface looks like this:
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
In the logPaginatedResponse, I am trying to get autocompletion for response.data.meta.pagination.total, response.data.meta.pagination.per_page, etc.
The AxiosResponse interface gives me autocompletion for response, but no autocompletion for anything in the data object.
The problem is, the data object on the response could be one of many interfaces. See below:
interface CustomerResponse {
data: {
customer_id: number
},
meta: {
pagination: {
total: number,
count: number,
per_page: number,
current_page: number,
total_pages: number,
links: {
previous: string,
current: string,
next: string
}
}
},
}
interface ProductResponse {
data: {
product_id: number
},
meta: {
pagination: {
total: number,
count: number,
per_page: number,
current_page: number,
total_pages: number,
links: {
previous: string,
current: string,
next: string
}
}
},
}
export const logPaginatedResponse = async (response: AxiosResponse<CustomerResponse | ProductResponse>) => { // console.dir here }
Is there any way to give logPaginatedResponse either the CustomerResponse or ProductResponse interface dynamically?
I tried passing CustomerResponse or ProductResponse to the logPaginatedResponse function at the time of function invocation as follows:
const response = await axios.get(url) logPaginatedResponse<CustomerResponse>(response)
But that isn't doing the trick. Is this not possible? It almost sounds like I'm looking for what this SO post describes: https://stackoverflow.com/a/50512697 but I'm not entirely sure.
Any suggestions would be super appreciated!! Thank you so much.
EDIT:
I ended up refactoring per u/__gc's suggestion in the comments