Reputation: 1447
I'm having trouble creating a generic-based callback event handler function that I want to pass as prop down to my component.
onNodeClick
function defined using generics & when i use it in isolation, it works.// ✅ Simple example of calling a generic function
const onNodeClick = <T,> (event:any) => {
return null as unknown as T;
}
const string_result = onNodeClick<string>(event_from_somewhere)
However, when I try to pass this method as a prop to my component, I am getting errors. I'm unsure of how to resolve it
Live Typescript Code Playground
import React from 'react';
type NodeComponentProps = {
onNodeClick: <T>(event: any) => T;
};
export const NodeComponent = ({onNodeClick}: NodeComponentProps) => {
return null;
}
const Homepage = () => {
const handleNodeClick = <T,>(event: any): T => {
return null as unknown as T;
};
return (
<NodeComponent
onNodeClick={(event): string => {
const string_result = handleNodeClick<string>(event); // ✅ correct type
return string_result; // ❌ onNodeClick is throwing type error; see error message a few lines below
}}
/>
)
}
/*
Type '<T>(event: any) => string' is not assignable to type '<T>(event: any) => T'.
Type 'string' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'string
*/
Upvotes: 3
Views: 2740
Reputation: 4010
I think you want the type to be generic, not the function. If the function is generic, then it should be callable with angle brackets and work correctly. For example, the identity function works with any type, so it should pass your generic function definition:
const Homepage = () => {
const onNodeClick = <T>(x: T): T => {
return x;
};
return (
<NodeComponent
onNodeClick={onNodeClick}
/>
)
}
However, the function you used will always return a string. If you tried to call it with <number>
, it would fail. Therefore, not a generic function.
By contrast, if you make the type generic, you should be able to specify you are using it with a string:
Here is a Playground link
type NodeComponentProps<T> = {
onNodeClick: (event: any) => T;
};
export const NodeComponent = <T,>({onNodeClick}: NodeComponentProps<T>) => {
return null;
}
Upvotes: 2