Code is:
const foo = (foo: string) => {
const result = []
result.push(foo)
}
I get the following TS error:
[ts] Argument of type 'string' is not assignable to parameter of type 'never'.
What am I doing wrong? Is this a bug?
All you have to do is define your result as a string array, like the following:
const result : string[] = [];
Without defining the array type, it by default will be never. So when you tried to add a string to it, it was a type mismatch, and so it threw the error you saw.
never[] ? is there ever a use for that except "an array that will ALWAYS be empty?"nevers will be useful. But while looking into it I came across this answer which has great info.let x; ) it is of type any by default. Not never.any[]. Was surprised it was never[] which makes it useless. Unintuitive. Thanks for the answer. edit: grammarAnother way is:
const result: any[] = [];
any isn't a good option, because it basically turns off any TypeScript features. It's a workaround and can lead to various bugs.const result: any[] = [] be more accurate? its an array of any not and array treated as anyThis seems to be some strange behavior in typescript that they are stuck with for legacy reasons. If you have the code:
const result = []
Usually it would be treated as if you wrote:
const result:any[] = []
however, if you have both noImplicitAny FALSE, AND strictNullChecks TRUE in your tsconfig, it is treated as:
const result:never[] = []
This behavior defies all logic, IMHO. Turning on null checks changes the entry types of an array?? And then turning on noImplicitAny actually restores the use of any without any warnings??
It's unintuitive that adding an additional type check (noImplicitAny) results in more relaxed type checking, especially when it introduces the thing you were attempting to eliminate.
I was having same error In ReactJS statless function while using ReactJs Hook useState. I wanted to set state of an object array , so if I use the following way
const [items , setItems] = useState([]);
and update the state like this:
const item = { id : new Date().getTime() , text : 'New Text' };
setItems([ item , ...items ]);
I was getting error:
Argument of type '{ id: number; text: any }' is not assignable to parameter of type 'never'
but if do it like this,
const [items , setItems] = useState([{}]);
Error is gone but there is an item at 0 index which don't have any data(don't want that).
so the solution I found is:
const [items , setItems] = useState([] as any);
useState at the time of initialization, as suggested by @neiya: const [items , setItems] = useState<any[]>([]); const foo = (foo: string) => {
const result: string[] = []
result.push(foo)
}
You needed specify what the array is since result = [] has a return type of any[]. Typically you want to avoid any types since they are meant to be used as an "Escape hatch" according to Microsoft.
The result is an object that is an array of string.
The solution i found was
const [files, setFiles] = useState([] as any);
as any thwarts a static typing system. If you know what type or types will be housed in the array, it's much better to be explicit: const myArray: string[] = []; const [files, setFiles] = useState(myArray);. Note in the case of useState, you can pass in a generic, instead: const [files, setFiles] = useState<string[]>([]);as any you are just saying "nah I don't want to use typescript". Neiya's answer on the other hand is good enough. A better approach should be interface, but I am new to typescript as well, so I am not sure how to interface this one.const outside my component as const initialEmailsState: string[] = []; and used it inside the the component with useState as const [emails, setEmails] = useState(initialEmailsState); and now I can set emails like this without problems: setEmails([...emails, createOption(inputValue)]);I was able to get past this by using the Array keyword instead of empty brackets:
const enhancers: Array<any> = [];
Use:
if (typeof devToolsExtension === 'function') {
enhancers.push(devToolsExtension())
}
Array keyword yet is another good way. It is even more semantically useful in case you have to define a type for an array of arrays like this let parsed: Array<[]> = [];[][]. If you wanted something like an array of array of numbers you could do number[][]. On that note, do consider that: parsed: Array<[]> here is implicitly Array<any[]>Error: Argument of type 'any' is not assignable to parameter of type 'never'.
In tsconfig.json -
"noImplicitReturns": false,
"strictNullChecks":false,
Solution: type as 'never'
any.Remove "strictNullChecks": true from "compilerOptions" or set it to false in the tsconfig.json file of your Ng app. These errors will go away like anything and your app would compile successfully.
Disclaimer: This is just a workaround. This error appears only when the null checks are not handled properly which in any case is not a good way to get things done.
One more reason for the error.
if you are exporting after wrapping component with connect()() then props may give typescript error
Solution: I didn't explore much as I had the option of replacing connect function with useSelector hook
for example
/* 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} />
}
I got the error when defining (initialising) an array as follows:
let mainMenu: menuObjectInterface[] | [] = [];
The code I got the problem in:
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
}
})
The error was: TS2322: Type 'any' is not assignable to type 'never'
The reason was that the array was initialised with also the option of an empty array. Typescript saw a push to a type which also can be empty. Hence the error.
Changing the line to this fixed the error:
let mainMenu: menuObjectInterface[] = [];
In case you are using TypeScript with Vue and you are facing this issue in data when initializing the variable. you can try this {} as any.
export default defineComponent({
name: "Student",
data() {
return {
studentList: {} as any,
}
}
......
})
Note: Usually as a best practice, we discourage any, so replace any with your Object model. like studentList: {} as StudentModel. where Student model can be a Interface like this:
export interface StudentModel {
studentId: number,
fullName: string,
grade: string
}
any should be discouraged in favour of using TS properly. I use it too here and there, however it's just a convenient escape hatch. This is in case a newbie glances at this answer.I did a workaround by doing
const array = new Array()
array.push(123)
console.log(array) // => [123]
I received the same error
Argument of type 'string' is not assignable to parameter of type 'never'.
in a jasmine test:
const toggleModalSpy = spyOn(component, 'toggleUpload').and.callThrough();
The actual error was that the component had no 'toggleUpload' method. It took me some time to figure it out. 😂
in latest versions of angular, you have to define the type of the variables:
if it is a string, you must do like that:
public message : string ="";
if it is a number:
public n : number=0;
if a table of string:
public tab: string[] = [];
if a table of number:
public tab: number[]=[];
if a mixed table:
public tab: any[] = []; .......etc (for other type of variables)
if you don't define type of variable: by default the type is never
NB: in your case, you must know the type of variables that your table must contain, and choose the right option (like option 3 ,4 5 ).
This error occurs when you set the value of a property in an object when you haven't set the properties of the object. Declare a type for the object with its properties, then assign the type when you instantiated the object. Now you can set the values of the properties without this error.
I had this error for useRef
before with error:
const revealRefs = useRef([]);
const addToRefs = (el) => {
if (el && !revealRefs.current.includes(el)) {
revealRefs.current.push(el);
}
};
after without error:
const revealRefs = useRef<HTMLElement[]>([]);
const addToRefs = (el: HTMLElement | null) => {
if (el && !revealRefs.current.includes(el)) {
revealRefs.current.push(el);
}
};
And i just added a file inside src with name typings.d.ts
with this line in the file
declare var ClipboardJS: any;
and magically it worked. NO such type never issues occurred then.
ClipboardJS which is incorrect according to the typings (whether your code is wrong, or the typings were wrong). This won't just magically fix all instances of the error. Like the one the question shows off const arr = []; will be types as never[]. Adding a random global definition doesn't change that arr has no type information for what goes in the array.
const result: [] = []=>const result: string[], not just[], butstring[], if you don't know the type inside the array, you can always fallback toany[]