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>([]);