tsx文件中的通用类型解析

时间:2017-08-16 14:51:36

标签: typescript tsx

我试图了解在typescript中使用tsx文件来键入推断是否存在限制。

如果我创建无状态反应组件:

interface TestProps {
    foo: string;
}

export const TestComp: React.StatelessComponent<TestProps> = x => {
    return(<div>{foo}</div>);
};

然后在第二个tsx文件中尝试以下操作:

import { TestComp } from './TestComp';

const getProperties = function<P>(node: React.ReactElement<P>) : P {
    return node.props
};

var props1 = getProperties(React.createElement(TestComp, { foo : 'bar' }));
var props2 = getProperties(<TestComp foo='bar' />);

props1将具有 TestProps 的推断类型,props2将具有任何的推断类型。

我的印象是最后两行相同。 Typescript是否认为第二次调用中的对象是React.ReactElement<any>

2 个答案:

答案 0 :(得分:1)

这里只是一些语法混淆。你的箭头功能没有按照你的想法做到:

export const TestComp: React.StatelessComponent<TestProps> = x => {
    return(<div>{foo}</div>);
};

已将x标记为any。此外,x甚至不在函数中使用。你真正想要的是:

export const TestComp: React.StatelessComponent<TestProps> = (x: TestProps) => {
    return(<div>{x.foo}</div>);
};

顺便说一下,关于箭头功能的快速文体说明:如果我不得不使用bind,我通常只使用箭头功能。在这个简单的例子中,我实际上更喜欢使用普通函数,因为this没有时髦的业务。

答案 1 :(得分:1)

迈克尔的回答指出了我正确的方向,因为它让我深入研究了React的.d.ts文件,但实际原因更为微妙。

这段代码

export const TestComp: React.StatelessComponent<TestProps> = x => {
    return(<div>{foo}</div>);
};

使用在反应.d.​​ts中定义的接口:

interface StatelessComponent<P = {}> {
    (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null;
    ...
}

这表明x的推断类型为TestProps & { children?: ReactNode }。这很好用,可以在VS Code的intellisense结果中看到。

然而,该函数的返回类型并不像我预期的那样<{em> ReactElement<TestProps>,它是ReactElement<any>

通过比较,createElement定义为:

function createElement<P>(
    type: SFC<P>,
    props?: Attributes & P,
    ...children: ReactNode[]): SFCElement<P>;

,其中

type SFC<P = {}> = StatelessComponent<P>;
interface SFCElement<P> extends ReactElement<P> { }

调用React.createElement(TestComp, { foo : 'bar' })允许来自TestProps的{​​{1}}的通用参数一直冒泡到最终创建的元素中。

总结:通过明确地将TestComp定义为TestComp,我还将工厂函数中返回的元素定义为StatelessComponent<TestProps>。删除此定义并将组件写为:

ReactElement<any>

export function TestComp(x: TestProps) {
    ...
}

提供Typescript less 信息并允许它推断出正确的类型,而不是强迫它使用错误的类型......