繁体   English   中英

当 T 为条件时,TypeScript 无法推断泛型类型

[英]TypeScript can't infer generic type when T is conditional

我正在尝试编写一个 React 组件,它的属性根据通用属性的类型而变化。

interface PropsBase<T> {
  value: T;
  children: (value: T) => ReactElement;
}

type ArrayType<T extends any[]> = T extends Array<infer U> ? U : never;

interface ArrayProps<T extends any[]> extends Omit<PropsBase<T>, 'children'> {
  children: (value: ArrayType<T>, index: number, array: T) => ReactElement;
}

type Props<T> = T extends any[] ? ArrayProps<T> : PropsBase<T>;

const MyComp = <T extends any>({ value, children }: Props<T>) => {
  if (Array.isArray(value)) {
    return <>{value.map(children)}</>;
  }
  
  return <div>{children(value)}</div>;
};

如果value是一个数组,那么它期望的子元素是一个应用于数组中每个元素的函数。 否则,它需要一个只接收值的函数。

由于我尚未确定的原因,当Props是上述条件时,它无法确定T的类型。

const val = { a: 10 };
const rendered = 
  <MyComp value={val}>
    {value => <span>{value.a}</span>}
  </MyComp>;

// error: Object is of type 'unknown'.

即使三元运算符的两个结果相同,情况也是如此。

type Props<T> = T extends any[] ? PropsBase<T> : PropsBase<T>;
// same error

任何其他道具,包括仅在ArrayProps中列出的道具,都可以正确推断。

interface ArrayProps<T extends any[]> extends Omit<PropsBase<T>, 'children'> {
  children: (value: ArrayType<T>, index: number, array: T) => ReactElement;
  arrayOpt: boolean;
}

const array = [ 1, 2, 3 ];
const renderedArray =
  <MyComp value={array} arrayOpt>
    {value => <span>{value}</span>}
  </MyComp>;

如果我不得不猜测,这是 tsc 中的一个错误。 同时,有没有办法解决这个问题?

TS游乐场

这很混乱,但我找到了解决方法。

interface MyComp<T> extends FunctionComponent<Props<T>> {};
function MyComp<T extends any[]>(props: ArrayProps<T>): ReactElement;
function MyComp<T>(props: PropsBase<T>): ReactElement;
function MyComp<T>(props: Props<T>) {
  const {
    value,
    children,
    arrayOpt,
  } = props as PropsBase<T> & { arrayOpt: boolean };

  if (Array.isArray(value)) {
    return <>{value.map(children)}</>;
  } else {
    return <div>{(children as PropsBase<T>['children'])(value)}</div>;
  }
};

TS游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM