【问题标题】:What is "not assignable to parameter of type never" error in TypeScript?TypeScript 中的“不可分配给类型参数从不”错误是什么?
【发布时间】:2019-02-24 16:33:22
【问题描述】:

代码是:

const foo = (foo: string) => {
  const result = []
  result.push(foo)
}

我收到以下 TS 错误:

[ts] 'string' 类型的参数不可分配给'never' 类型的参数。

我做错了什么?这是一个错误吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    如下定义(初始化)数组时出现错误:

    let mainMenu: menuObjectInterface[] | [] = [];
    

    我遇到问题的代码:

    let mainMenu: menuObjectInterface[] | [] = [];
    dbresult.rows.forEach((m) => {
        if (!mainMenu.find((e) => e.menucode === m.menucode)) {
            // Not found in mainMenu, yet
            mainMenu.push({menucode: m.menucode, menudescription: m.menudescription})  // Here the error
        }
    })
    

    错误是:TS2322:类型“any”不可分配给类型“never”

    原因是该数组也使用空数组选项进行了初始化。 Typescript 看到了一个也可以为空的类型的推送。因此出现错误。

    将行更改为此修复了错误:

    let mainMenu: menuObjectInterface[] = [];
    

    【讨论】:

      【解决方案2】:

      假设您的 linter 可以使用“任何”类型:

      如果您不知道将填充数组的值的类型,您可以这样做,result 将推断类型。

      const result: any[] = []
      

      【讨论】:

        【解决方案3】:

        您只需将结果定义为任意数组,如下所示:

        结果:任意 = [];

        【讨论】:

        • 这在其他答案中已经提到了。
        【解决方案4】:

        这似乎是打字稿中的一些奇怪行为,由于遗留原因,他们一直坚持。如果你有代码:

        const result = []
        

        通常会被视为您写的:

        const result:any[] = []
        

        但是,如果您的 tsconfig 中同时具有 noImplicitAny FALSE、AND strictNullChecks TRUE,则将其视为:

        const result:never[] = []
        

        这种行为违反了所有逻辑,恕我直言。打开空检查会更改数组的条目类型??然后开启noImplicitAny居然恢复使用any没有任何警告??

        当您确实有一个 any 数组时,您不需要用额外的代码来表示它。

        【讨论】:

        • 没错,这绝对是不直观的,一个名为“no implicit any”的参数应该暗示任何时候都会假设某事是任何的——它不是。此外,隐含的“从不”似乎很愚蠢,为什么不简单地声明一个错误:数组没有声明其类型。恕我直言,这应该完全取决于 noImplicitAny,而不是组合。
        • 我认为为大型 repos 做出贡献的人有时会过度设计它。至少我们知道应该设置哪些标志以使其直观。至于我,我将两个标志都设置为 true 并且感觉很好。
        【解决方案5】:

        您也可以添加as string[]

        const foo = (foo: string) => {
          const result = []
          (result as string[]).push(foo)
        }
        

        当它是对象的一部分时我这样做了

        let complexObj = {
        arrData : [],
        anotherKey: anotherValue
        ...
        }
        (arrData as string[]).push('text')
        

        【讨论】:

          【解决方案6】:

          我在 ReactJS 函数组件中遇到了同样的错误,使用 ReactJS useState 钩子。

          解决方案是在初始化时使用尖括号声明 useState 的类型:

          // Example: type of useState is an array of string
          const [items , setItems] = useState<string[]>([]); 
          

          【讨论】:

          • 如果您使用 React state + TypeScript 并遇到“不可分配给'never'类型的参数”,这就是正确的答案。错误。谢谢!
          • 轰隆隆!非常感谢您的回答!正是我需要的。
          【解决方案7】:

          错误:“any”类型的参数不能分配给“never”类型的参数。

          在 tsconfig.json -

            "noImplicitReturns": false,
          
             "strictNullChecks":false,
          

          解决方案:输入“从不”

          【讨论】:

          • 感谢上帝严格的 NullChecks:false。对于小型一次性项目,我无法忍受这种东西。不过,我可以理解他们为什么要为大型项目这样做。
          【解决方案8】:

          错误的另一个原因。

          如果您在使用 connect()() 包装组件后导出,则 props 可能会出现打字稿错误解决方案:我没有探索太多,因为我可以选择用 useSelector 钩子替换连接函数
          例如

          /* Comp.tsx */
          interface IComp {
           a: number
          }
          
          const Comp = ({a}:IComp) => <div>{a}</div>
          
          /* ** 
          
          below line is culprit, you are exporting default the return 
          value of Connect and there is no types added to that return
          value of that connect()(Comp) 
          
          ** */
          
          export default connect()(Comp)
          
          
          --
          /* App.tsx */
          const App = () => {
          /**  below line gives same error 
          [ts] Argument of type 'number' is not assignable to 
          parameter of type 'never' */
           return <Comp a={3} />
          }
          

          【讨论】:

            【解决方案9】:

            我找到的解决方案是

            const [files, setFiles] = useState([] as any);
            

            【讨论】:

            • 使用as any 会阻止静态类型系统。如果您知道数组中将包含哪些类型,最好明确表示:const myArray: string[] = []; const [files, setFiles] = useState(myArray);。注意在useState的情况下,你可以传入一个泛型,而不是:const [files, setFiles] = useState&lt;string[]&gt;([]);
            • 这是一种不好的做法。通过使用as any,您只是在说“不,我不想使用打字稿”。另一方面,宁亚的回答已经足够好了。更好的方法应该是接口,但我也是打字稿的新手,所以我不确定如何接口这个。
            • 我不敢相信这个答案有这么多的赞成票,这基本上是在沉默打字稿,完全违背了它的目的。
            【解决方案10】:

            "compilerOptions" 中删除 "strictNullChecks": true 或在 中将其设置为 false >tsconfig.json 文件的 Ng 应用程序。这些错误会像任何事情一样消失,您的应用会成功编译。

            免责声明:这只是一种解决方法。仅当未正确处理空检查时才会出现此错误,这在任何情况下都不是完成工作的好方法。

            【讨论】:

            • 对我来说,在 tsconfig 中只是“严格”部分,当我将它设置为 false 时,你说错误消失,这是反应,而不是 angular。谢谢。
            【解决方案11】:

            我在使用 ReactJs Hook 时在 ReactJS statless 函数中遇到了同样的错误 useState。 我想设置对象数组的状态,所以如果我使用以下方式

            const [items , setItems] = useState([]);
            

            并像这样更新状态:

             const item = { id : new Date().getTime() , text : 'New Text' };
             setItems([ item , ...items ]);
            

            我收到错误:

            类型为 '{ id: number; 的参数; text: any }' 不能分配给“never”类型的参数

            但如果这样做,

            const [items , setItems] = useState([{}]);
            

            错误消失了,但 0 索引 处有一个项目没有任何数据(不想要那个)。

            所以我找到的解决方案是:

            const [items , setItems] = useState([] as any);
            

            【讨论】:

            • 实际上,我认为您的解决方案的更好版本是 const [items , setItems] = useState([] as string[]);
            【解决方案12】:

            您所要做的就是将您的result 定义为一个字符串数组,如下所示:

            const result : string[] = [];
            

            不定义数组类型,默认为never。因此,当您尝试向其添加字符串时,它是类型不匹配的,因此会引发您看到的错误。

            【讨论】:

            • 这对我来说似乎很奇怪,为什么默认为 never[] ?除了“一个永远为空的数组”之外,还有什么用处?
            • 我完全同意,因为老实说,我想不出一个nevers 数组会有用的用例。但是在调查它时,我发现了这个answer,它有很好的信息。
            • 默认类型不应该是“any”吗?当您声明一个变量 (let x;) 时,默认情况下它的类型为 any。不是never
            • @VincentBuscarello 我猜,这种默认值的主要目的是让一个总是向他们的数组添加类型;但错误信息绝对没有帮助。
            • 我总是想知道这些更改发生在源代码中的哪些地方以便更好地理解,所以对于那些好奇的人来说,请参阅:github.com/Microsoft/TypeScript/issues/9976github.com/microsoft/TypeScript/pull/8944
            【解决方案13】:

            我能够通过使用 Array 关键字而不是空括号来解决这个问题:

            const enhancers: Array<any> = [];
            

            用途:

            if (typeof devToolsExtension === 'function') {
              enhancers.push(devToolsExtension())
            }
            

            【讨论】:

            • 感谢您的指出。 Array 关键字是另一种好方法。如果您必须为这样的数组数组定义一个类型,它在语义上更有用let parsed: Array&lt;[]&gt; = [];
            【解决方案14】:

            另一种方法是:

            const result = [] as  any;
            

            【讨论】:

            • 实际上使用any 不是一个好的选择,因为它基本上会关闭任何 TypeScript 功能。这是一种解决方法,可能会导致各种错误。
            • 是的。但有时其他方法都不起作用,尤其是当您使用第三方库时..
            • const result: any[] = [] 会更准确吗?它是一个任意非数组,并且数组被视为任意
            • @g00dnatur3 是对的。如果必须使用 any,那么至少指定它是任何类型的项的数组。
            【解决方案15】:

            您需要在字符串数组const result: string[] = []; 中键入result

            【讨论】:

              猜你喜欢
              • 2022-01-06
              • 2022-06-19
              • 1970-01-01
              • 2021-07-06
              相关资源
              最近更新 更多