I’ve got this TypeScript error and I don’t fully understand what’s going on:
src/helpers.ts:11:14 - error TS2322: Type '<T extends "horizontal" | "vertical" | undefined, U extends AriaRole | undefined>(ariaOrientation: T, role: U) => "horizontal" | "vertical" | NonNullable<T> | "both"' is not assignable to type 'ResolveOrientationFunction'.
Type '"horizontal" | "vertical" | NonNullable<T> | "both"' is not assignable to type 'NonNullable<T> | "both"'.
Type '"horizontal"' is not assignable to type 'NonNullable<T> | "both"'.
Here is my function:
import { type HTMLAttributes } from "react";
type ResolveOrientationFunction = <
T extends HTMLAttributes<HTMLElement>["aria-orientation"],
U extends HTMLAttributes<HTMLElement>["role"]
>(
ariaOrientation: T,
role: U
) => "both" | NonNullable<T>;
export const resolveOrientation: ResolveOrientationFunction = (ariaOrientation, role) => {
if (ariaOrientation === undefined) {
switch (role) {
case "menubar":
case "slider":
case "tablist":
case "toolbar": {
return "horizontal";
}
case "listbox":
case "menu":
case "scrollbar":
case "tree": {
return "vertical";
}
}
}
return ariaOrientation ?? "both";
};
The function is supposed to return "both" | "horizontal" | "vertical"
.
HTMLAttributes<HTMLElement>["aria-orientation"]
is actually "horizontal" | "vertical" | undefined
and HTMLAttributes<HTMLElement>["role"]
is React.AriaRole | undefined
.
I’m actually trying to make this function match the type "both" | NonNullable<HTMLAttributes<HTMLElement>["aria-orientation"]>
.
2
Answers
While I agree with jcalz’s comment, the intent to make this function generic might not be what you to achieve eventually. But I will try to explain why this snippet is giving an error.
If you notice the return type
NonNullable<T>
, it actually means a value that is of the typeT
. Now,T
can be anything as long as it extendsHTMLAttributes<HTMLElement>["aria-orientation"]
. In the function however, we’re returning either only ahorizontal
or avertical
or aboth
but as per the return type it needs to be of typeT
Which can be more than just
vertical
,horizontal
orboth
.We can fix this by using non generic return type (which is what we’re actually returning as well). When we replace
NonNullable<T>
withHTMLAttributes<HTMLElement>["aria-orientation"]
it works.Here’s your example with a non generic return type.
Hope this helps! 🙂
Your
ResolveOrientationFunction
type definition,is generic in both
T
, the type ofariaOrientation
, andU
, the type ofrole
. It returns a value of type"both" | NonNullable<T>
. So ifT
isundefined
becauseariaOrientation
isundefined
, then the function must return"both" | NonNullable<undefined>
which is"both"
. But your implementation doesn’t do that. It can instead return"horizontal"
or"vertical"
depending onrole
.So your
resolveOrientation
function is not a validResolveOrientation
.It’s not clear that you need the function to be generic at all. Certainly the
U
type parameter isn’t useful as written, since it has no effect on the return type. And you don’t really want theT
type parameter to be reflected directly in the output type either. It seems like your return type should just be"both" | "vertical" | "horizontal"
without reference toT
orU
. And if you have a generic function where there’s no obvious dependency on the type parameters, then you might not want a generic function in the first place.If you change the generics to specific types like this:
Then your function compiles cleanly:
Playground link to code