I am experimenting with concurrent mode and suspense in React and am getting a type error when I am trying to drill some mock data from a parent component to a child component because my promise wrapper does not inherently know about the type that is getting read. The error message I am getting is:
TS2739: Type '{ data: any; }' is missing the following properties from type 'MockData': title, name, address, city
How can I have my promise wrapper know about the kind of type that is getting returned to it without explicitly saying export const promiseWrapper = (promise: Promise<MockData>): PromiseWrapper => {...
since I want to be using this promise wrapper for other fetches that may return other interfaces? Thanks!
sampleComponent.tsx:
import * as React from 'react';
import api, { MockData } from 'api/api';
const resource = api.getMockData();
const SampleComponent: React.FC = () => {
const mockData = resource.mockData.read();
return (
<ChildComponent mockData={mockData} /> // type error received here
);
};
interface ChildProps {
mockData: MockData;
}
const ChildComponent: React.FC<ChildProps> = ({ mockData }) => (
<div>
<h1>{mockData.title}</h1>
<h1>{mockData.name}</h1>
<h1>{mockData.address}</h1>
<h1>{mockData.city}</h1>
</div>
);
api.ts:
import { PromiseWrapper, promiseWrapper } from './promiseWrapper';
export interface Resource {
[key: string]: PromiseWrapper;
}
export interface MockData {
title: string;
name: string;
address: string;
city: string;
}
const mockData = {
title: 'this is a title',
name: 'John Smith',
address: '102 Street',
city: 'Pittsburgh',
};
const mockDataPromise = (): Promise<{ data: MockData }> => new Promise((resolve) => {
setTimeout(() => {
resolve({
data: mockData,
});
}, 1000);
});
const getMockData = (): Resource => {
const getMockDataPromise = mockDataPromise();
return {
mockData: promiseWrapper(getMockDataPromise),
};
};
export default {
getMockData,
};
promiseWrapper.ts:
export interface PromiseWrapper {
read(): {
data: any;
};
}
export const promiseWrapper = (promise: Promise<any>): PromiseWrapper => {
let status = 'pending';
let result: object;
const suspender = promise.then(
(r) => {
status = 'success';
result = r;
},
(e) => {
status = 'error';
result = e;
},
);
return {
// @ts-ignore
// eslint-disable-next-line consistent-return
read() {
if (status === 'pending') {
throw suspender;
} else if (status === 'error') {
throw result;
} else if (status === 'success') {
return result;
}
},
};
};