You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript报错:new表达式缺构造签名、参数不匹配问题求助

解决TypeScript reducer中throw new Error的类型错误

报错信息

在reducer函数的default分支执行throw new Error('Action unknown');时,出现两个TypeScript报错:

  • 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009)
  • Expected 0 arguments, but got 1.ts(2554)

问题代码

import { useEffect, useReducer } from 'react';
import Header from './Header';
import MainContent from './MainContent';
import Loader from './Loader';
import Error from './Error';
import StartScreen from './StartScreen';
import Question from './Question';

interface Question {
  question: string;
  options: string[];
  correctOption: number;
  points: number;
}

type State = {
  questions: Question[];
  status: 'ready' | 'error' | 'loading' | 'active' | 'finished';
  index: number;
};

export type Action =
  | {
      type: 'dataReceived';
      payload: Question[];
    }
  | {
      type: 'dataFailed';
    }
  | {
      type: 'unknown';
    }
  | {
      type: 'start';
    };

const initialState: State = {
  questions: [],

  // "loading", "error", "ready", "active", "finished"
  status: 'loading',
  index: 0,
};

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'dataReceived':
      return {
        ...state,
        questions: action.payload,
        status: 'ready',
      };
    case 'dataFailed':
      return {
        ...state,
        status: 'error',
      };
    case 'start':
      return {
        ...state,
        status: 'active',
      };
    default:
      throw new Error('Action unknown');
  }
}

function App() {
  const [{ questions, status, index }, dispatch] = useReducer(
    reducer,
    initialState
  );
  const numQuestions: number = questions.length;

  useEffect(function () {
    fetch('http://localhost:8000/questions')
      .then(res => res.json())
      .then(data => dispatch({ type: 'dataReceived', payload: data }))
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      .catch(_err => dispatch({ type: 'dataFailed' }));
  }, []);

  return (
    <div className="app">
      <Header />
      <MainContent>
        {status === 'loading' && <Loader />}
        {status === 'error' && <Error />}
        {status === 'ready' && (
          <StartScreen numQuestions={numQuestions} dispatch={dispatch} />
        )}
        {status === 'active' && <Question question={questions[index]} />}
      </MainContent>
    </div>
  );
}

export default App;

错误原因

核心问题是命名冲突:你导入了自定义的React组件Error(import Error from './Error';),这个组件名直接覆盖了全局的原生Error构造函数。当你在reducer里执行new Error('Action unknown')时,TypeScript会把这里的Error识别为你导入的自定义组件,而非原生Error类:

  • 自定义Error组件是React组件,没有构造签名(不能用new关键字实例化),触发第一个报错;
  • 自定义组件的渲染逻辑不需要传入字符串参数,你传入了'Action unknown',触发第二个报错。

解决方案

给自定义的Error组件重命名,避免和全局Error构造函数冲突:

  1. 修改导入语句,给组件起别名:
import ErrorComponent from './Error';
  1. 在JSX渲染中使用别名:
{status === 'error' && <ErrorComponent />}

修改后,new Error('Action unknown')会正确指向原生Error构造函数,两个报错都会消失。


内容的提问来源于stack exchange,提问作者Markewycz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:42:37