How can I make argument assignable to proper parameter? - reactjs

I am new to typescript and I have following error bound with setFilteredColumns(obj)
Argument of type '(false | Column)[]' is not assignable to parameter of type 'SetStateAction<Column[] | undefined>'.
Type '(false | Column)[]' is not assignable to type 'Column[]'.
Type 'false | Column' is not assignable to type 'Column'.
Type 'boolean' is not assignable to type 'Column'.ts(2345)
interface ColumnsHeader {
title: string;
disp: boolean;
}
export interface Column {
col: ColumnsHeader;
}
interface IProps{
tocompare:Column[];
columns:Column[]
}
const useBuildColumns = ({tocompare, columns}:IProps) => {
const [filteredColumns, setFilteredColumns] = useState<Column[]>();
useEffect(() => {
let obj = tocompare &&
tocompare.map((k:Column, ii:number) => {
return columns[ii] && columns[ii].col.disp === true && k;
})
setFilteredColumns(obj);
}, [columns]);
return [filteredColumns];
};
How can I resolve this error?

The problem is that you use logical operators everywhere, even where it leads to a distortion of the result. In your example map function can return false.
I didn't quite understand what was going in useEffect, maybe you tried to make something like this:
useEffect(() => {
if (tocompare) {
let obj = tocompare.filter(
(k: Column, ii: number) => columns[ii] && columns[ii].col.disp
);
setFilteredColumns(obj);
}
}, [columns]);
Remember that logical operators returns a boolean value

Related

Typescript error when use react useState hook with generics

When I use generic type in react useState hook, I have a weird error:
// From react typings
type SetStateAction<S> = S | ((prevState: S) => S);
type Dispatch<A> = (value: A) => void;
declare function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
// Declare generic response type
type TDataResponse<T> = { type: 'success'; data: T; };
type TErrorResponse = { type: 'error'; error: string; };
type TResponse<T> = TDataResponse<T> | TErrorResponse;
function loadData<T, U = TResponse<T>>() {
const [data, setData] = useState<U | null>(null);
// ERROR: Argument of type '{ type: string; error: string; }' is not assignable to parameter of type 'SetStateAction<U | null>'.
// Object literal may only specify known properties, and 'type' does not exist in type '(prevState: U | null) => U | null'.(2345)
setData({ type: 'error', error: 'error message'});
}
But if use useState<TResponse<T> | null> there is no error:
function loadData2<T, U = TResponse<T>>() {
const [data2, setData2] = useState<TResponse<T> | null>(null);
// No error
setData2({ type: 'error', error: 'error message'});
}
Typescript Playground
it's not weird at all - in given syntax (function loadData<T, U = TResponse<T>>() {...}) the U type can be "anything" - so it's not possible for TypeScript to know what may it be during the runtime as only U sub-types are assignable to it, and the { type: 'error', error: 'error message'} is not a sub-type of U
it won't get any better if you will change the definition to function loadData<T, U extends TResponse<T> = TResponse<T>>() {...}, because situation is the same, the U type just got narrower though
in situation like this one you can't use generics for internal values (so the correct definition would be just function loadData<T>() {...}), unless you somehow get the U type from somewhere, eg.
function loadData<T, U = TResponse<T>>(loader: () => U) {
const [data, setData] = useState<U | null>(null)
setData(loader());
}
loadData<number>(() => ({ type: 'error', error: 'it works, lol' }))

Typescript Generic fix

I am new to typescript and facing issue on following for loop function. "typeof NO_PLANNING_DATA | Record<string, string | number>[] | undefined" this is the type for the data which i am passing to the "updateData" function. Since "undefined" also a type for the passing data, getting type issue for "data?.forEach" section. How to make this as a generic type.
const updateData = <T extends typeof NO_PLANNING_DATA | Record<string, string | number>[] | undefined>(data: T) => {
const items: { [x: string]: number }[] = [];
data?.forEach((val: { [x: string]: number }, index: number) => {
items[index] = {};
for (const key in val) {
if (key === "on_premise" || key === "row") {
items[index][key] = val[key];
} else {
items[index][key] = 0;
}
}
});
return items;
};

Argument of type 'unknown' is not assignable to parameter of type 'string', with array.includes()

There are some similar questions but my situation is different. I am working on a text editor and this is my code:
const LIST_TYPES = ["numbered-list", "bulleted-list"];
const toggleBlock = (editor: Editor, format: string) => {
const isActive = isBlockActive(editor, format);
const isList = LIST_TYPES.includes(format);
// Wrap nodes at the specified location in the element container. If no location is specified, wrap the selection.
Transforms.unwrapNodes(editor, {
match: (n: Node) =>
LIST_TYPES.includes(
!Editor.isEditor(n) && SlateElement.isElement(n) && n.type
),
split: true,
});
const newProperties: Partial<SlateElement> = {
type: isActive ? "paragraph" : isList ? "list-item" : format,
};
Transforms.setNodes(editor, newProperties);
if (!isActive && isList) {
const block = { type: format, children: [] };
Transforms.wrapNodes(editor, block);
}
};
match() takes Node as argument. I passed a correct type. However In this expression !Editor.isEditor(n) && SlateElement.isElement(n) && n.type, when I hover over each statemnt, .isEditor(n), .isElement(n) and n.type gives me the same warning: "Argument of type 'unknown' is not assignable to parameter of type 'string'" even though I passed the correct type as argument. I dont event understand where "unknown" coming from.
this is type for unwrapNodes()
unwrapNodes(editor: import("..").Editor, options: {
at?: import("..").Path | import("..").Point | import("..").Range | undefined;
match?: ((node: import("..").Node) => boolean) | undefined;
mode?: "highest" | "lowest" | "all" | undefined;
split?: boolean | undefined;
voids?: boolean | undefined;
}): void;
I think the issue is with includes(). Somehow it does not evaluate this !Editor.isEditor(n) && SlateElement.isElement(n) && n.type. Because this works : match: (n: Node) => LIST_TYPES.includes(n.type as string)
I think i figured out just by wrapping the logical statement and assigning it as string
Transforms.unwrapNodes(editor, {
match: (n: Node) =>
LIST_TYPES.includes(
(!Editor.isEditor(n) && SlateElement.isElement(n) && n.type) as string
),
split: true,
});

Why got "This expression is not callable..." errors from typescript and react js?

I'm new of typescript. I don't know why got the error.
my data list array:
const {
data: CUData = { cu: [] as Array<CuType> },
} = useGetCUQuery();
let CUDataArray = CUData && CUData.cu? CUData.cu:null;
const ownCompany = CUDataArray !== null && CUDataArray.filter(
company => (company.isOwner && company.userType === 2)
);
const assignedCompany = CUDataArray!== null && CUDataArray.filter(
company => (!company.isOwner && company.userType === 3)
);
Error is:
> This expression is not callable.
Each member of the union type '{ <S extends CuType>(cb: (value: CuType, index: number, array: CuType[]) => value is S, thisArg?: any): S[]; (cb: (value: CuType, index: number, array: CuType[]) => unknown, thisArg?: any): CuType[]; } | { ...; }' has signatures, but none of those signatures are compatible with each other. TS2349
Typescript isn't sure if the type for the array CUDataArray is CuType[] or unknown[]. The source of this confusion is coming from the return type of your useGetCUQuery() function. If you edit your post with that function I can look at it.
const {
data: CUData = { cu: [] as Array<CuType> },
} = useGetCUQuery();
Note that the as Array<CuType> here only applies to the empty array which you are using as a default, not to the variable CUData if it comes from data.
Ultimately you want to fix the unknown return type at its source, which is the useGetCUQuery() function. But we can also apply a type to the variable that we get from it. Does this help at all?
type CUQueryVal = {
data?: {
cu?: Array<CuType>
}
}
const queried: CUQueryVal = useGetCUQuery();
const { data: CUData = { cu: [] } } = queried; // 'as' is no longer needed
Playground Link

What is MomentInput type in ReactJS with Typescript?

I have an event where I recognise if it's a moment date input (material-ui-pickers) or normal text input.
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const isDateInput = moment.isMoment(event);
const dateValue = () => {
return moment(event).format();
};
}
And I have an error from typescript:
No overload matches this call.
Overload 1 of 2, '(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment', gave the following error.
Argument of type 'ChangeEvent' is not assignable to parameter of type 'MomentInput'.
Type 'ChangeEvent' has no properties in common with type 'MomentInputObject'.
Overload 2 of 2, '(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment', gave the following error.
Argument of type 'ChangeEvent' is not assignable to parameter of type 'MomentInput'.
Type 'ChangeEvent' has no properties in common with type 'MomentInputObject'.
What type should event have to resolve the error?
The solution is to add moment.Moment interface like below:
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement> & moment.Moment) => {
const isDateInput = moment.isMoment(event);
const dateValue = () => {
return moment(event).format();
};
}

Resources