【问题标题】:What is "not assignable to parameter of type never" error in TypeScript?什么是 TypeScript 中的“不可分配给永不类型的参数”错误?
【发布时间】:2022-01-06 20:55:16
【问题描述】:

代码是:

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

我收到以下 TS 错误:

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

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

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您所要做的就是将您的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
    【解决方案2】:

    另一种方法是:

    const result = [] as  any;
    

    【讨论】:

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

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

    const result = []
    

    通常会被视为您写的:

    const result:any[] = []
    

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

    const result:never[] = []
    

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

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

    【讨论】:

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

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

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

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

    【讨论】:

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

    我找到的解决方案是

    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,您只是在说“不,我不想使用打字稿”。另一方面,宁亚的回答已经足够好了。更好的方法应该是接口,但我也是打字稿的新手,所以我不确定如何接口这个。
    • 我不敢相信这个答案有这么多的赞成票,这基本上是在沉默打字稿,完全违背了它的目的。
    【解决方案6】:

    我在使用 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[]);
    【解决方案7】:

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

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

    const result: any[] = []
    

    【讨论】:

      【解决方案8】:

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

      const enhancers: Array<any> = [];
      

      用途:

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

      【讨论】:

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

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

      在 tsconfig.json -

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

      解决方案:输入“从不”

      【讨论】:

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

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

      【讨论】:

        【解决方案11】:

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

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

        【讨论】:

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

        错误的另一个原因。

        如果您在使用 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} />
        }
        

        【讨论】:

          【解决方案13】:

          您也可以添加as string[]

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

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

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

          【讨论】:

            【解决方案14】:

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

            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[] = [];
            

            【讨论】:

              【解决方案15】:

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

              结果:任意 = [];

              【讨论】:

              • 这在其他答案中已经提到了。
              猜你喜欢
              • 2022-06-19
              • 2019-02-24
              • 1970-01-01
              • 2021-08-19
              相关资源
              最近更新 更多