React Js uses API calls to retrieve data for its components. The API calls usually return JSON data. If I use Typescript in my React Js application, I must cast the JSON response to a compatible Typescript interface to access the JSON response data. Let's see how to achieve that.
JSON response object
I will use the below JSON response to design my interface. It covers most of the scenarios we encounter in JSON responses.
{
"contactDetails": {
"firstName": "Micky",
"lastName": "Mouse",
"email": "mm@disneyland.com",
"address": {
"street": "Some street",
"city": "Anaheim",
"state": "CA",
"zip": "9280"
},
"phone": [{
"number": "1800-Disney",
"type": "home"
},
{
"number": "1800-Disney",
"type": "cell"
}
]
},
"workDetails": {
"companyName": "LearnBestCoding",
"address": {
"street": "Some street",
"city": "Edmond",
"state": "OK",
"zip": "73034"
},
"phone": {
"number": "1800-work",
"type": "direct"
}
},
"experience": {
"releventExperience": "10 years",
"company": [{
"name": "Company 1",
"position": "Research Scientist",
"fromTo": "2022 - Present"
}, {
"name": "Company 2",
"position": "Research Assistant",
"fromTo": "2012 - 2021"
}, {
"name": "Company 3",
"position": "Architect",
"fromTo": "2011 - 2012"
}]
},
"education": {
"institutions": [{
"name": "UCO",
"certification": "BSc Computer Science"
}, {
"name": "UCLA",
"certification": "MSc Computer Science"
}]
}
}
Design interface to match JSON response
I can break down my JSON response into four main objects.
{
contactDetails: {},
workDetails: {},
experience: {},
education: {}
}
Now let's take a look at the contactDetails
object. It has an address object and an array of phone numbers.
contactDetails: {
address: {},
phone: []
}
Now I have built a skeleton for the contactDetails
object. Let's fill in the rest of the properties to
complete the contactDetails
.
contactDetails: {
firstName: string
lastName: string
email: string
address: {
street: string
city: string
state: string
zip: string
},
phone: {
type: string
number: string
}[]
}
The workDetails
object also contains the address
and phone
objects.
workDetails: {
companyName: string
address: {
street: string
city: string
state: string
zip: string
},
phone: {
type: string
number: string
}
}
The experience
and education
objects can be composed like the below.
experience: {
releventExperience: string
company: {
name: string
position: string
fromTo: string
}[]
}
education: {
institutions: {
name: string
certification: string
}[]
}
The address
and phone
objects are common for contactDetails
and workDetails
objects.
Therefore, bringing those two into two separate interfaces is a good practice.
interface Address {
street: string
city: string
state: string
zip: string
}
interface Phone {
type: string
number: string
}
With that change, my contactDetails
and workDetails
objects look like the below.
contactDetails: {
firstName: string
lastName: string
email: string
address: Address,
phone: Phone[]
}
workDetails: {
companyName: string
address: Address,
phone: Phone
}
Next, I must pick a meaningful name for the entire object. The interface name Candidate
sounds like a good candidate.
Here is the complete code example of what I have explained here. For the sake of simplicity, I don't call an API.
Instead, I use a hard-coded JSON. So I can contain the entire example into a single file.
import styles from './Table.module.css'
const json = {
"contactDetails": {
"firstName": "Micky",
"lastName": "Mouse",
"email": "mm@disneyland.com",
"address": {
"street": "Some street",
"city": "Anaheim",
"state": "CA",
"zip": "9280"
},
"phone": [{
"number": "1800-Disney",
"type": "home"
},
{
"number": "1800-Disney",
"type": "cell"
}
]
},
"workDetails": {
"companyName": "LearnBestCoding",
"address": {
"street": "Some street",
"city": "Edmond",
"state": "OK",
"zip": "73034"
},
"phone": {
"number": "1800-work",
"type": "direct"
}
},
"experience": {
"releventExperience": "10 years",
"company": [{
"name": "Company 1",
"position": "Research Scientist",
"fromTo": "2022 - Present"
}, {
"name": "Company 2",
"position": "Research Assistant",
"fromTo": "2012 - 2021"
}, {
"name": "Company 3",
"position": "Architect",
"fromTo": "2011 - 2012"
}]
},
"education": {
"institutions": [{
"name": "UCO",
"certification": "BSc Computer Science"
}, {
"name": "UCLA",
"certification": "MSc Computer Science"
}]
}
}
interface Address {
street: string
city: string
state: string
zip: string
}
interface Phone {
type: string
number: string
}
interface Candidate {
contactDetails: {
firstName: string
lastName: string
email: string
address: Address,
phone: Phone[]
}
workDetails: {
companyName: string
address: Address,
phone: Phone
}
experience: {
releventExperience: string
company: {
name: string
position: string
fromTo: string
}[]
}
education: {
institutions: {
name: string
certification: string
}[]
}
}
const response: Candidate = json
const App = () => {
return <table className={styles.customers}>
<tr><td>First Name</td><td>{response.contactDetails.firstName}</td></tr>
<tr><td>Last Name</td><td>{response.contactDetails.lastName}</td></tr>
<tr><td>Email</td><td>{response.contactDetails.email}</td></tr>
<tr>
<td>Address</td>
<td>
{response.contactDetails.address.street}<br/>
{response.contactDetails.address.city}<br/>
{response.contactDetails.address.state}<br/>
{response.contactDetails.address.zip}
</td>
</tr>
<tr>
<td>Phone</td>
<td>{response.contactDetails.phone.map((phone) => {
return <>{`${phone.type} ${phone.number}`}<br/></>
})}</td>
</tr>
<tr><td>Company</td><td>{response.workDetails.companyName}</td></tr>
<tr>
<td>Address</td>
<td>
{response.workDetails.address.street}<br/>
{response.workDetails.address.city}<br/>
{response.workDetails.address.state}<br/>
{response.workDetails.address.zip}
</td>
</tr>
<tr>
<td>Phone</td>
<td>{`${response.workDetails.phone.type} ${response.workDetails.phone.number}`}</td>
</tr>
<tr><td>Experience</td><td>{response.experience.releventExperience}</td></tr>
<tr>
<td>Companies</td>
<td>{response.experience.company.map((exp) => {
return <>{`${exp.name} ${exp.position} ${exp.fromTo}`}<br/></>
})}</td>
</tr>
<tr>
<td>Education</td>
<td>{response.education.institutions.map((institute) => {
return <>{`${institute.name} ${institute.certification}`}<br/></>
})}</td>
</tr>
</table>
}
export default App;