简体   繁体   English

Typescript 基于变量动态分配泛型类型

[英]Typescript dynamically assign generic type based on a variable

I want to use a type (or interface) to extends a React component.我想使用类型(或接口)来扩展 React 组件。

Definition:定义:

type CoreProps<T> = {
  htmlElement?: 'article' | 'aside' // ...
} & React.HTMLAttributes<T>

Usage desired:所需用途:

type MyComponentProps = {
  myComponentFirstProp: string
  // ...
}

const MyComponent = ({ 
  htmlElement, 
  myComponentFirstProp,
  ...props
}: MyComponentProps & CoreProps): JSX.Element => {
  // ...
}

I know I can replace <T> by HTMLElement but is there a way to type CoreProps according to the input htmlElement passed in MyComponent ?我知道我可以用HTMLElement替换<T> ,但是有没有办法根据在MyComponent中传递的输入htmlElement键入CoreProps

There is JSX.IntrinsicElements type in which you can obtain relevant HTMLAttributes , so you can do it in this way.JSX.IntrinsicElements类型,您可以在其中获取相关HTMLAttributes ,因此您可以通过这种方式进行操作。

interface CoreProps<T> {
  htmlElement: T;
}

interface MyComponentProps {
  myComponentFirstProp?: string;
}

const MyComponent = <T extends keyof JSX.IntrinsicElements>(
  props: CoreProps<T> & JSX.IntrinsicElements[T] & MyComponentProps
): JSX.Element => {
  ...
};

<MyComponent htmlElement="img" src="." />; // OK
<MyComponent htmlElement="a" href="." />; // OK
<MyComponent htmlElement="article" />; // OK
<MyComponent htmlElement="a" src="." />; // Error, no 'src' attribute in <a> element

If you want the corresponding type of attributes如果你想要对应类型的属性

import { DetailedHTMLFactory, ReactHTML } from 'react';

type EleAttributes<
  T extends keyof ReactHTML
> = ReactHTML[T] extends DetailedHTMLFactory<infer R, infer P> ? R : never;

EleAttributes<'input'>
EleAttributes<'aside'>
...

Update更新

Based your example:根据您的示例:

type CoreProps<T extends keyof JSX.IntrinsicElements> = {
  htmlElement?: T;
} & JSX.IntrinsicElements[T];

type ComponentProps = {
  display?: string;
};

const Component = <T extends keyof JSX.IntrinsicElements>({
  htmlElement,
  display,
  style,
  children,
  ...props
}: ComponentProps & CoreProps<T>) => {
  const styles = {
    ...style,

    display,
    // more ...
  };

  // Set default 'div' when htmlElement is undefined
  return React.createElement(
    htmlElement || 'div',
    {
      style: styles,
      ...props,
    },
    children
  );
};

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

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