ChatGPT解决这个技术问题 Extra ChatGPT

TypeScript 中的“不可分配给类型参数从不”错误是什么?

代码是:

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

我收到以下 TS 错误:

[ts]“字符串”类型的参数不可分配给“从不”类型的参数。

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

const result: [] = [] => const result: string[]只是 [],而是 string[],如果您不知道数组内部的类型,您可以随时回退到 any[]

Y
YakovL

您只需将 result 定义为字符串数组,如下所示:

const result : string[] = [];

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


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

另一种方法是:

const result: any[] = [];

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

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

const result = []

通常它会被视为你写的:

const result:any[] = []

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

const result:never[] = []

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

当您真正拥有一个 any 数组时,您不需要用额外的代码来指示它。


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

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

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

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

I
ImFarhad

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

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

并像这样更新状态:

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

我收到错误:'{ id: number; 类型的参数;文本:任何 }' 都不能分配给“从不”类型的参数

但如果这样做,

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

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

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

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

实际上,我认为您的解决方案的更好版本是 const [items , setItems] = useState([] as string[]);
L
Lakshan Hettiarachchi

我找到的解决方案是

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

使用 as any 会阻碍静态类型系统。如果您知道数组中将包含什么类型,最好明确表示:const myArray: string[] = []; const [files, setFiles] = useState(myArray);。请注意,在 useState 的情况下,您可以传入一个泛型,而不是:const [files, setFiles] = useState<string[]>([]);
这是一个不好的做法。通过使用 as any,您只是在说“不,我不想使用打字稿”。另一方面,宁亚的回答已经足够好了。更好的方法应该是接口,但我也是打字稿的新手,所以我不确定如何接口这个。
我不敢相信这个答案有这么多赞成,这基本上是在沉默打字稿,完全违背了它的目的。
@jmealy 你的回答对我有用,应该是解决这个问题的方法。按照您的示例,我将组件外部的 const 声明为 const initialEmailsState: string[] = [];,并在组件内部使用它,将 useState 用作 const [emails, setEmails] = useState(initialEmailsState);,现在我可以像这样设置 emails 而不会出现问题:setEmails([...emails, createOption(inputValue)]);
S
Shah

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

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

const result: any[] = []

2022 年 4 月 26 日:回到这个问题,我认为您可能一直在寻找的解决方案可能是这样的:

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

您需要指定数组是什么,因为 result = [] 的返回类型为 any[]。通常,您希望避免使用任何类型,因为根据 Microsoft 的说法,它们旨在用作“逃生舱口”。

结果是一个对象,它是一个数组,它需要类型字符串值或包含字符串的东西,例如 string |数字。


M
Mickers

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

const enhancers: Array<any> = [];

利用:

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

感谢您指出。 Array 关键字是另一种好方法。如果您必须为像 let parsed: Array<[]> = []; 这样的数组定义类型,它在语义上更有用
@ValentineShi 您仍然可以执行 [][] 之类的操作。如果你想要一个数字数组之类的东西,你可以做 number[][]。请注意:这里的 parsed: Array<[]> 是隐含的 Array<any[]>
r
rohit.khurmi095

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

在 tsconfig.json -

  "noImplicitReturns": false,

   "strictNullChecks":false,

https://i.stack.imgur.com/hLgbO.png

解决方案:输入“从不”

https://i.stack.imgur.com/huAF7.png


A
Ashutosh Singh

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

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


对我来说,在 tsconfig 中只是“严格”部分,当我将它设置为 false 时,你说错误消失,这是反应,而不是 angular。谢谢。
A
Akshay Vijay Jain

错误的另一个原因。如果您在使用 connect()() 包装组件后导出,则道具可能会给出打字稿错误解决方案:我没有进行太多探索,因为我可以选择用 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} />
}

d
domready

您需要将 result 输入到字符串 const result: string[] = []; 的数组中。


B
BertC

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

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:类型“任何”不可分配给类型“从不”

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

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

let mainMenu: menuObjectInterface[] = [];

H
Hadar Shpivak

您还可以添加 as string[]

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

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

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

M
Mounir bkr

在最新版本的 Angular 中,您必须定义变量的类型:

如果它是一个字符串,你必须这样做: public message : string ="";如果是数字: public n : number=0;如果是字符串表: public tab: string[] = [];如果是数字表:公共选项卡:数字[]=[];如果是混合表: public tab: any[] = []; .......等(对于其他类型的变量)如果您没有定义变量的类型:默认情况下,类型是 never

注意:在您的情况下,您必须知道表必须包含的变量类型,并选择正确的选项(如选项 3 ,4 5 )。