【问题标题】:React Typescript: FunctionComponent with templated propsReact Typescript:带有模板化道具的 FunctionComponent
【发布时间】:2019-12-10 06:09:33
【问题描述】:

我有一个带有模板化道具的组件:

const MyComponent = <Value extends any>({ value }: MyComponentProps<Value>) => <div />;

我可以在不明确指定 Value 类型的情况下使用它(它是推断的):

<MyComponent value="1" />
<MyComponent value={1} />

我通常这样写我的组件:

const MyComponent: FunctionComponent<MyComponentProps> = ({ value }) => <div />;

但还没有找到使用这种语法模板化MyComponentMyComponentProps 的方法...有人知道该怎么做吗?提前致谢!

【问题讨论】:

  • 你的目标到底是什么?
  • 我有一个接受{ views: { key: Key }[], initialView?: Key } 的选项卡组件,因此initialView 始终是views[].key 之一。第一种语法效果很好,但我总是使用第二种语法,想知道在这种情况下是否可以使用它:)

标签: reactjs typescript generics typescript-generics


【解决方案1】:

这就是我的工作

export type MyCompProps<ItemType> = {
    item: ItemType;
};

export const MyComp = <ItemType>(props: MyCompProps<ItemType>): React.ReactElement => {
    return <Text>item.toString</Text>;
}

那我可以打电话了

<MyComp item={myItem} />

它会弄明白。

【讨论】:

  • 完美运行,谢谢!我们可以用const MyComp: VFC&lt;Props&gt; 符号来做到这一点吗?
  • 另外,你有 Typescript 官方文档可以参考这个符号吗?
【解决方案2】:

根据您的评论,您只想要这个:

interface MyComponentProps<V> {
    views: V;
    initialView: keyof V;
}

type KeyedFunctionComponent<T> = FunctionComponent<MyComponentProps<T>>;

const MyComponent: KeyedFunctionComponent<Views> = (views, initialViews) => <div />;

然后使用接口或“typeof views”作为通用参数声明您的函数组件。我认为这很好。但是,您真正想要的是将它与生成器结合使用,这将允许您正确绑定和模板:

// Declare some views constant:
const views = { home: "home", index: "index" };


// Declare a type for our bound views component
interface KeyedProps<V> {
    initialView?: keyof V;
}


// declare a type for our input function
interface KeyedWithViewsProps<V> extends KeyedProps<V> {
    views: V;
}


// This is the binding function itself
function createKeyedComponent<T>(views: T, toWrap: FunctionComponent<KeyedWithViewsProps<T>>): FunctionComponent<KeyedProps<T>> {
    return (props: KeyedProps<T>) => toWrap({views, initialView: props.initialView});
}


// Call the binder, and pass in the function we want to bind.
const MyComponent = createKeyedCompnonet(views, () => <div />);

// Now, using the component, only requires the optional initialView param, and it it type-checked to ensure it is a member of views
<MyComponent initialView="home" /> // works
<MyComponent initialView="other" /> // doesn't work


【讨论】:

  • 编辑澄清一点,希望这很清楚,但可惜我不知道在 Typescript 中如何调用所有内容(但),这限制了我的解释
  • 看看我的编辑。我想这就是你想要的。
【解决方案3】:

如果您希望value 是任何类型:

type MyComponentProps = {
  value: any
};

或只是一种显式类型(也称为联合类型):

type MyComponentProps = {
  value: string | number
};

const MyComponent: FunctionComponent<MyComponentProps> = ({ value }) => <div />;

【讨论】:

    【解决方案4】:

    你可以像这样扩展你的 ComponentProps:

    interface MyComponentProps<T> {
       value: T
    }
    
    const MyComponent: FunctionComponent<MyComponentProps<string>> = ({ value }) => <div />;
    

    现在值是你传入 的任何值,例如字符串或任何值。

    【讨论】:

    • 是的,问题是在我的第一个示例中推断出泛型,我不想将其传递给接口
    • 你能详细说明你的代码吗?您想如何使用该组件?
    • 编辑澄清一下,希望这很清楚,但可惜我不知道在 Typescript 中如何调用所有内容(还),这限制了我的解释
    • 如果您只是希望它是 any(如第一个示例中所示),只需将 value 设置为 any:interface MyComponentProps { value: any }
    猜你喜欢
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 2020-08-14
    • 2017-11-28
    相关资源
    最近更新 更多