打字稿:使用接受组件实例的外部函数来响应渲染

时间:2019-03-18 06:45:54

标签: reactjs typescript type-inference

我正在创建一堆内部具有一些常用功能的组件,其中一个是处理渲染的组件。简化后,它看起来像这样:

public Static Class GlobalVariable
{
  Currency="$";
}

TypeScript对此设置并不满意,并说:const render = ( instance: React.Component<{}, {flag: boolean}>, cb: () => React.ReactNode ) => instance.state.flag ? cb() : ''; class Test extends React.Component<{}, {flag: boolean}> { state = {flag: true}; render() { return render(this, () => '') } } 就我个人而言,我看不到该参考。

作为一个可能的线索,如果我这样重写这段代码:

'render' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.

...一切正常,但由于目前尚看不到某些复杂性,我真的想使用组件本身。

出什么问题了?我可以用这个通用功能做什么,以使TypeScript不会争论吗?


UPD::通过一些测试,我创建了一个更接近所需示例的示例:

const render = (
    state: {flag: boolean},
    cb: () => React.ReactNode
) => state.flag ? cb() : '';

class Test extends React.Component<{}, {flag: boolean}> {
    state = {flag: true};
    render() { return render(this.state, () => '') }
}

这里的要点是以下事实:外部type Component<T> = React.Component<{}, {flag: T}> const render = <T>( instance: Component<T>, cb: () => React.ReactNode ) => instance.state.flag ? cb() : ''; class Test extends React.Component<{}, {flag: boolean}> { state = {flag: true}; render() { const result = render(this, () => ''); return result; } inner = () => 'test'; } 函数是泛型的,并且render类型取决于泛型参数,因此TypeScript无法代替{{1 }}。是否可以在不失去类型安全性的情况下帮助他?

1 个答案:

答案 0 :(得分:1)

这里的问题似乎与渲染函数中实例参数的类型推断有关。

让我们看看

  • 即使您将实例类型标记为React.Component,当typescript尝试推断呈现类型时,它也必须使用必须是React.Component <>的'this'实例来做到这一点,它必须提取呈现类成员也是,然后重新开始。所以我想打字稿决定放弃这种推断
type RenderF = (
    instance: React.Component<any, any>,
    cb: () => React.ReactNode) => React.ReactNode;

const render: RenderF = (
    instance: React.Component<{}, {flag: boolean}>,
    cb: () => React.ReactNode
) => instance.state.flag ? cb() : null;

class Test extends React.Component<{}, {flag: boolean}> {
    state = {flag: true};
    render() { return render(this, () => null) }
}
  • 因此一个简单的解决方案是将RenderF实例参数标记为任意,以避免打字稿推断再次检查该实例。
type RenderF = (
    instance: any, // <-----
    cb: () => React.ReactNode) => React.ReactNode;

const render: RenderF = (
    instance: React.Component<{}, {flag: boolean}>,
    cb: () => React.ReactNode
) => instance.state.flag ? cb() : null;

class Test extends React.Component<{}, {flag: boolean}> {
    state = {flag: true};
    render() { return render(this, () => null) }
}

UPD

如果您不想在实例参数中放弃类型安全性,则只能指定新类型中需要的类型

interface FlagComponent {
    state: { flag: boolean }
}

type RenderF = (
    instance: FlagComponent,
    cb: () => React.ReactNode) => React.ReactNode;

const render: RenderF = (
    instance: React.Component<{}, {flag: boolean}>,
    cb: () => React.ReactNode
) => instance.state.flag ? cb() : null;

class Test extends React.Component<{}, {flag: boolean}> {
    state = {flag: true};
    render() { return render(this, () => null) }
}