Home > Net >  Typescript : not assignable to type never TS2345
Typescript : not assignable to type never TS2345

Time:02-18

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

Further reading

  • Related