Dan*_*ser 3 jsx typescript reactjs
我正在描述一个React库,它通过一个名为的属性获取组件或HTML标记名称as.给定as属性时,它会从该组件/标记名称创建一个元素,并传递任何其他给定的属性.
这里有些例子:
<Foo as="a" href="https://example.com" />
<Foo as={FancyButton} fancyButtonAttr="hello!" />
Run Code Online (Sandbox Code Playgroud)
我知道Semantic UI与增强功能类似.我如何在TypeScript中输入?
我将举一个这里给出的最基本要求的例子.你可以尝试推广一些更复杂的东西.
首先,这是我们的神奇组成部分!
import * as React from "react";
function Foo<Tag extends AnyTag>(props: { as: Tag } & PropsOf<Tag>): JSX.Element;
Run Code Online (Sandbox Code Playgroud)
注意两件事:
AnyTagPropsOf那是我们的公开签名.我们可能能够使用该签名以类型安全的方式实现它,但我们可以在实现签名中"欺骗"一点.这取决于您作为实施者.
function Foo(props: any) {
    return <div>Implementation goes here!</div>
}
Run Code Online (Sandbox Code Playgroud)
让我们回到我们提到的那两种类型.AnyTag是JSX标签可以是任何东西.
type AnyTag = string
            | React.FunctionComponent<never>
            | (new (props: never) => React.Component);
Run Code Online (Sandbox Code Playgroud)
PropsOf 尝试获取给定HTML标记名称或组件的预期属性.
type PropsOf<Tag> =
    Tag extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[Tag] :
    Tag extends React.ComponentType<infer Props> ? Props & JSX.IntrinsicAttributes :
    never
;
Run Code Online (Sandbox Code Playgroud)
现在让我们定义一些使用相同道具的组件 - 一个函数和一个类.
interface SomeProps {
  x: boolean; y: boolean; z: boolean;
}
function Bar(props: SomeProps) {
    return <div>{props.x} {props.y} {props.z}</div>;
}
class Baz extends React.Component<SomeProps> {
    render() {
        const { x, y, z } = this.props;
        return <div>{x} {y} {z}</div>;
    }
}
Run Code Online (Sandbox Code Playgroud)
现在这里有一些用法!
let a1 = <Foo as="a" href="https://kthxb.ai" />;         // good!
let a2 = <Foo as="div" href="https://kthxb.ai" />;       // error!
let a3 = <Foo as="a" href={100} />;                      // error!
let b1 = <Foo as={Bar} x y z />;                         // good!
let b2 = <Foo as={Bar} x y z asdsadsada />;              // error!
let b3 = <Foo as={Bar} x={1} y={2} z={3} asdsadsada />;  // error!
let c1 = <Foo as={Baz} x y z />;                         // good!
let c2 = <Foo as={Baz} x y z asdsadsada />;              // error!
let c3 = <Foo as={Baz} x={1} y={2} z={3} asdsadsada />;  // error!
Run Code Online (Sandbox Code Playgroud)
共
import * as React from "react";
// Here's our magic component!
// Note two things:
//   - A type called AnyTag
//   - A utility type called PropsOf
function Foo<Tag extends AnyTag>(props: { as: Tag } & PropsOf<Tag>): JSX.Element;
// That was our public signature. We might be able to implement this in a type-safe way using that signature,
// but we can "cheat" a little here in the implementation signature. This is up to you as the implementer.
function Foo(props: any) {
    return <div>Implementation goes here!</div>
}
// AnyTag is anything that a JSX tag can be.
type AnyTag = string
            | React.FunctionComponent<never>
            | (new (props: never) => React.Component);
// PropsOf tries to get the expected properties for a given HTML tag name or component.
type PropsOf<Tag> =
    Tag extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[Tag] :
    Tag extends React.ComponentType<infer Props> ? Props & JSX.IntrinsicAttributes :
    never
;
// Let's now define a few components taking the same props - one function and one class.
interface SomeProps {
  x: boolean; y: boolean; z: boolean;
}
function Bar(props: SomeProps) {
    return <div>{props.x} {props.y} {props.z}</div>;
}
class Baz extends React.Component<SomeProps> {
    render() {
        const { x, y, z } = this.props;
        return <div>{x} {y} {z}</div>;
    }
}
// Now here's some usage!
let a1 = <Foo as="a" href="https://kthxb.ai" />;         // good!
let a2 = <Foo as="div" href="https://kthxb.ai" />;       // error!
let a3 = <Foo as="a" href={100} />;                      // error!
let b1 = <Foo as={Bar} x y z />;                         // good!
let b2 = <Foo as={Bar} x y z asdsadsada />;              // error!
let b3 = <Foo as={Bar} x={1} y={2} z={3} asdsadsada />;  // error!
let c1 = <Foo as={Baz} x y z />;                         // good!
let c2 = <Foo as={Baz} x y z asdsadsada />;              // error!
let c3 = <Foo as={Baz} x={1} y={2} z={3} asdsadsada />;  // error!
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           1040 次  |  
        
|   最近记录:  |