I am creating custom hook useArray in react with Typescript, I am using Generics for array type as i want any possible value as array element,but then when i try to push any number then it gives me error: Type 'number' is not assignable to type 'never'. and same for any other type as well.if i initialise my array with some values then only that values can be pushed again and not any other values.How to solve this issue?
Here i am providing code : useArray.ts :
import { useState } from "react";
type CompType = string | number;
export default function useArray<T extends CompType>(defaultValue: T[]): {
array: T[],
set: React.Dispatch<SetStateAction<T[]>>,
push: (elemet: T) => void,
remove: (index: number) => void,
filter: (callback: (n: T) => boolean) => void,
update: (index: number, newElement: T) => void,
clear: () => void
} {
const [array, setArray] = useState(defaultValue);
function push(element: T) {
setArray((a) => [...a, element]);
}
function filter(callback: (n: T) => boolean) {
setArray((a) => a.filter(callback));
}
function update(index: number, newElement: T) {
setArray((a) => [
...a.slice(0, index),
newElement,
...a.slice(index 1, a.length),
]);
}
function remove(index: number) {
setArray((a) => [...a.slice(0, index), ...a.slice(index 1, a.length)]);
}
function clear() {
setArray([]);
}
return { array, set: setArray, push, filter, update, remove, clear };
ArrayComp.tsx :
import useArray from "./useArray";
function ArrayComp() {
const { array, set, push, remove, filter, update, clear } = useArray([]);
return (
<div>
<h1>Updated array: </h1>
<div> {array.join(", ")} </div>
<button onClick={() => set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])}>
set to[1, 2, 3, 4, 5, 6, 7, 8, 9,10]
</button>
<button onClick={() => push(5)}> Add 5 </button>
<button onClick={() => push("Hello")}> Add "Hello" </button>
<button onClick={() => update(3, 5)}> update 5 at index 3 </button>
<button onClick={() => filter((n) => n < 10)}>
filter numbers less than 10
</button>
<button onClick={() => remove(3)}> Remove forth Element </button>
<button onClick={clear}> Empty array </button>
</div>
);
}
export default ArrayComp;
App.tsx :
import "./App.css";
import ArrayComp from "./components/ArrayComp";
function App() {
return (
<div className="App">
<h1>React Custom Hook useArray()</h1>
<ArrayComp />
</div>
);
}
export default App;
CodePudding user response:
When calling useArray()
you passed an empty array []
. React doesn't really know which type the elements in the array should have based on the empty array, so he assigns T
the type unknown
.
One possible solution would be to specify the correct type when calling useArray()
.
const {
array, set, push, remove, filter, update, clear
} = useArray<string | number>([])
Another way to solve this is to make the defaultValue
optional.
function useArray<T extends CompType>(defaultValue?: T[]): /* ... */ {
if (!defaultValue || defaultValue.length === 0) {
defaultValue = []
}
/* ... */
}
If you use useArray()
now without any args typescript will assign CompType
to T
.
const { array, set, push, remove, filter, update, clear } = useArray()