I'm working on a web application, in which, one web page, I have to get objects of scenarios from database and show them using AG Grid in ReactJs.
This is the code of my functional component:
interface ScenarioTableProps {
name: String,
scenarios: ScenarioView[];
setScenarioAndScenarioInput: OnChange<ScenarioView>;
}
const ScenarioTable: React.FC<ScenarioTableProps> = (props) => {
const { scenarios, setScenarioAndScenarioInput} = props;
function scenarioNameLink(scenario: ScenarioView){
const opportunityId: string | undefined = scenario.inputs.opportunity?.opportunityId
if(opportunityId===undefined) return ( <p> Not available </p> )
else return (
<Link
onClick={() => setScenarioAndScenarioInput(scenario)}
to={createAllocationOutputPageRoute({
opportunityId: opportunityId,
scenarioId: scenario.scenarioId
})}
className="link"
>
{scenario.scenarioName}
</Link>)
}
useEffect(() => {
setRowData(scenarios.map(scenario => {//error pointing this line at the start of word 'scenarios'
return {
opportunityName: scenario.inputs.opportunity?.opportunityName,
scenarioName: scenarioNameLink(scenario),
size: getSize(scenario),
summary: generateScenarioDescription(scenario),
status: getScenarioStatuses(scenario.scenarioStatuses),
dateLastUpdated: formatDateFromString(scenario.lastUpdateDate),
dealTeam: formatDateFromString(scenario.lastUpdateDate)
}
}))
}, [scenarios])
const [rowData, setRowData] = useState([]);
const columnDefs = [
{ field: 'opportunityName', headerName: 'Opportunity Name' },
{ field: 'scenarioName', headerName: 'Scenario Name', cellRendererFramework:(params)=>params.value },
{ field: 'size', headerName: 'Size' },
{ field: 'summary', headerName: 'Summary', cellRendererFramework:(params)=><div>{params.value}</div> },
{ field: 'status', headerName: 'Status', cellRendererFramework:(params)=>params.value },
{ field: 'dateLastUpdated', headerName: 'Date Last Updated', width: '130px' },
{ field: 'dealTeam', headerName: 'Deal Team' }
]
let defaultColDef = {
wrapText: true,
autoHeight:true,
flex: true,
resizable: true,
};
return (
<>
<div className="ag-theme-balham" style={{height:'600px', width:'100%'}}>
<AgGridReact
modules={AllModules}
columnDefs={columnDefs}
rowData={rowData}
defaultColDef={defaultColDef}
/>
</div>
</>
);
}
This is what the error says:
[frontend] TypeScript error in C:/Developer/IdeaProjects/myProject/SummaryPage.tsx(105,16):
[frontend] Argument of type '{ opportunityName: string | undefined; scenarioName: Element; size: string; summary: ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<...>)>; status: ReactElement<...>; dateLastUpdated: string; dealTeam: string; }[]' is not assignable to parameter of type 'SetStateAction<never[]>'.
[frontend] Type '{ opportunityName: string | undefined; scenarioName: Element; size: string; summary: ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<...>)>; status: ReactElement<...>; dateLastUpdated: string; dealTeam: string; }[]' is not assignable to type 'never[]'.
[frontend] Type '{ opportunityName: string | undefined; scenarioName: JSX.Element; size: string; summary: React.ReactElement<any, string | ((props: any) => React.ReactElement<any, any> | null) | (new (props: any) => React.Component<...>)>; status: React.ReactElement<...>; dateLastUpdated: string; dealTeam: string; }' is not assignable to type 'never'. TS2345
[frontend]
[frontend] 103 |
[frontend] 104 | useEffect(() => {
[frontend] > 105 | setRowData(scenarios.map(scenario => {
[frontend] | ^
[frontend] 106 | return {
[frontend] 107 | opportunityName: scenario.inputs.opportunity?.opportunityName,
[frontend] 108 | scenarioName: scenarioNameLink(scenario),
[frontend]
[frontend]
[frontend] npm ERR! code ELIFECYCLE
[frontend] npm ERR! errno 1
The error says I'm assigning to a parameter of type 'never'. I can't understand where I'm assigning, why is the parameter 'never' and how to get rid of it. Please help.
CodePudding user response:
Problem
setRowData is typed as follows:
type SetStateAction<S> = S | ((prevState: S) => S);
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
– [reference 1] and [reference 2]
setRowData is returned from calling useState, which you have done with the initial state being an empty array:
const [rowData, setRowData] = useState([]);
As a result S is inferred to be never[] and setRowData is expected to accept never[]. However you call setRowData with the results of mapping over scenarios:
setRowData(scenarios.map(scenario => { ... }))
This is why you get the type error saying the result of your map cannot be assigned to type never[].
Solution
You probably don't want never[], it's not a useful type. So you'd want to tell TypeScript to use your own type. You can do this by using useState's type parameter (S). Replace YourTypeHere with your own type:
const [rowData, setRowData] = useState<YourTypeHere>([]);
