You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript函数类型不匹配报错求助:resolveOrientation类型分配问题

解决TypeScript泛型函数返回类型不匹配报错TS2322

错误信息

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"'.

原代码

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";
};

错误原因

泛型定义的返回类型"both" | NonNullable<T>存在约束矛盾:

  • 当T被推断为undefined时,NonNullable<T>等于never,此时返回类型被收缩为"both"
  • 但函数在ariaOrientation为undefined时,实际返回了"horizontal"或"vertical",这两个值不在"both"类型范围内,导致类型不匹配

解决方案

方案1:使用条件类型适配泛型返回

修改ResolveOrientationFunction的返回类型,根据T是否为undefined动态调整允许的返回值:

import { type HTMLAttributes } from "react";

type ResolveOrientationFunction = <
  T extends HTMLAttributes<HTMLElement>["aria-orientation"],
  U extends HTMLAttributes<HTMLElement>["role"]
>(
  ariaOrientation: T,
  role: U
) => T extends undefined ? "both" | "horizontal" | "vertical" : "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";
};

这种方案保留了泛型的类型推断能力:当传入明确的"horizontal"或"vertical"时,函数返回类型会精确到对应值+"both";当传入undefined时,返回所有可能的方向值+"both"。

方案2:简化类型定义(放弃泛型精确推断)

如果不需要泛型带来的精确类型推断,可以直接定义固定的输入输出类型,代码更简洁:

import { type HTMLAttributes } from "react";

type Orientation = NonNullable<HTMLAttributes<HTMLElement>["aria-orientation"]>;
type ResolveOrientationFunction = (
  ariaOrientation: Orientation | undefined,
  role: HTMLAttributes<HTMLElement>["role"]
) => "both" | Orientation;

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";
};

这种方案直接明确函数返回"both" | "horizontal" | "vertical",完全符合你的预期返回类型,同时避免了泛型约束带来的冲突。

内容的提问来源于stack exchange,提问作者devatina11yb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:30:12