2

我试图了解在打字稿中使用 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 的推断类型为any

我的印象是最后两行是等价的。Typescript 是否有理由相信第二次调用中的 object 是 a React.ReactElement<any>

4

2 回答 2

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继续进行。

于 2017-08-16T19:38:58.097 回答
1

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

这段代码

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

使用在 react .d.ts 中定义的接口:

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

这表明x将具有推断类型TestProps & { children?: ReactNode }. 这工作正常,可以在 VS Code 的智能感知结果中看到。

但是,该函数的返回类型 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' })允许TestPropsfrom的通用参数TestComp一直冒泡到最终创建的元素中。

总结一下:通过明确定义TestComp为 aStatelessComponent<TestProps>我还将工厂函数返回的元素定义为 a ReactElement<any>。删除此定义并将组件编写为:

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

或者

export const TestComp = (x: TestProps) => {
    ....
}

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

于 2017-08-17T10:08:17.160 回答