angular 13 Passing parameter onclick, in a loop using - angular13

I have an array of objects. i am iterating that in loop and passing each item's name to onclick which targets a function navigate(url:string) in cmpenent.ts
html :
{{sousMenu.titre}}
compenent:
navigate(url:string):void{
this.router.navigate( [url]); }
the error message is :
Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
Type 'undefined' is not assignable to type 'string'.ngtsc(2345)

Can you provide a complete code example so we can advise on the total context.
Sometimes if a property is defined with a type of 'string | undefined' additional handling is needed when the function calls for only a 'string'.
Some of the things you can do are the following:
navigate(url:string | undefined):void{
this.router.navigate( [url as string]);
}
That might not be the best route but without further viewing of the code it's hard to see how we may expand on it.

Related

Typescript: Updating value of an object that has assignable type of 'never'

I have seen this issue explained from Bobby Hadz for arrays of the same type, but I cannot find anythinjg about objects that contain different types.
Here is the error that is produced.
Type 'string | number | boolean' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.
Here is the code that causes the TS error.
const geometryCopy : geometryTypes = {... geometryValues}
//Append the new value to the object
if(geometryCopy?.[attributeName]) geometryCopy[attributeName] = newValue
attributeName has its type as keyof geometryType.
Any help would be greatly appreciated on how to resolve the issue or any best practices that I am not following.
Edit: I have recreated the error on this ts playground.

React Hook Form with Typescript - Type 'UseFormRegister<User>' is not assignable to type 'LegacyRef<HTMLInputElement>'

I have a demo here
I'm trying to create a simple react hook form with typescript
I have the form displaying locally but for some reason it won't display here abd I get t.split is not a function this is not my question though.
On the inputs I am using ref={register} which is what I have seen in tutorials but on the ref I get the error
Type 'UseFormRegister<User>' is not assignable to type 'LegacyRef<HTMLInputElement>'. Type 'UseFormRegister<User>' is not assignable to type '(instance: HTMLInputElement) => void'. Types of parameters 'name' and 'instance' are incompatible. Type 'HTMLInputElement' is not assignable to type '"email" | "password" | "firstname" | "lastname" | "age" | "confirmpassword"'. Type 'HTMLInputElement' is not assignable to type '"confirmpassword"'.(2322) index.d.ts(137, 9): The expected type comes from property 'ref' which is declared here on type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'
Does anyone know why this is or how to fix this.
React Refs are of a specific type with a generic type attached (LegacyRef).
The type of register is UseFormRegister<User> which is not compatible with react refs.
Perhaps the tutorial you referenced used register in a different way or another parameter?

How to conditionally render a prop in TSX

I am trying to do the following in a functional component using TypeScript (I abstracted it a bit):
return <IonToast {canClose && button={close}}
It isn't allowed to wrap a prop inside a conditional. But what would be the best solution to have such logic?
I though about assigning the 'close' variable before the return, but since Ionic is an external component library, it doesn't accept an empty variable.
The IonToast is typed in node-modules with the following. So it doesn't like it if you pass anything but a valid value.
export interface ToastOptions {
buttons?: (ToastButton | string)[];
}
The ts error goes like this
Types of property 'button' are incompatible. Type 'string | boolean | undefined' is not assignable to type 'string | undefined'. Type 'false' is not assignable to type 'string | undefined'.
UPDATED
According to this document
You can have this logic for your buttons attribute
const buttons: ToastButton[] = canClose ? [close] : [] //`close` needs to be `ToastButton` type
return <IonToast buttons={buttons} />
OLD ANSWER
I don't know which is the best solution for this case, but I'm personally using this way
return <IonToast button={canClose ? close : () =>{}} />
The second param is an empty function that would help to prevent errors, just in case you call button() (indirect to close()) in IonToast component.
There are many solution to accomplish this. If you have many properties under the same condition you can wrap them in an object. Since IonToast expect props of a shape -> https://ionicframework.com/docs/api/toast#toastoptions you should use buttons instead of button
return <IonToast {...(canClose && {buttons:[close]})}

Having issues using Pick utility type with React useState hook

I'm trying to understand why can't I use Pick utility type to pick one property from my interface and use it to type my component's state.
Here's the interface:
export interface IBooking {
...
propertyId: string | null;
...
}
And then in my component I have the following:
const [propertyId, setPropertyId] = useState<Pick<IBooking, 'propertyId'>>('some-id');
This is the error I get:
TS2345: Argument of type 'string' is not assignable to parameter of type 'Pick | (() => Pick )'.
However, if I just replace Pick<IBooking, 'propertyId'> with string | null, it, of course, works. And I don't understand what is the difference. Isn't it exactly what Pick type should do? I didn't have much experience with utility types, but I'm using Pick type perfectly fine in another place. Is it because some specifics of useState hook?
What am I missing here?
Thanks in advance.
Assuming that propertyId on IBooking is of the type string | null then it will be the following type:
{
propertyId: string | null;
}
The result of Pick is an object containing only attributes which are listed.
You can use a lookup type like this instead:
IBooking["propertyId"]

typescript problem in implementing rtl support for material-ui with emotion

I am trying to implement rtl support in a project using material-ui, as described here. my problem is in stage 4.1. I am trying to create a new cache instance that uses the stylis-plugin-rtl. the example povided in the documentation is in javascript & I'm trying to port that into typescript. I have two problems. first, I am trying to pass stylis plugins to the createCache function but I get this error:
Type '(element: Element, index: number, children: Element[], callback: Middleware) => string | void' is not assignable to type 'Plugin'.
Types of parameters 'element' and 'context' are incompatible.
Type 'import("/home/ehsun/Desktop/volkswagen/packages/swiss-army-knife/node_modules/#emotion/stylis/types/index").Context' is not assignable to type 'Element'.ts(2322)
which I bypassed like this:
const cacheRtl = createCache({
key: 'muirtl',
stylisPlugins: [
(prefixer as unknown) as StylisPlugin,
(rtlPlugin as unknown) as StylisPlugin,
],
});
the second problem is that the CacheProvider component has a problem with the type of the created cache & gives this warning:
Property 'insert' is missing in type 'import("/node_modules/#emotion/utils/types/index").EmotionCache' but required in type 'import("/node_modules/#emotion/react/node_modules/#emotion/utils/types/index").EmotionCache'.ts(2741)
index.d.ts(26, 3): 'insert' is declared here.
index.d.ts(338, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps<EmotionCache>'
which I bypassed by casting the cache as any
<CacheProvider value={cacheRtl as any}>{children}</CacheProvider>
I feel like both solutions are wrong/incompelete, and a result of me being a bit inexperienced with typescript, so I would love to know if you people had a better idea. thanks in advance.

Resources