打字稿:使用接受组件实例的外部函数进行反应渲染
Typescript: React render using external function which accepts component instance
我正在创建一堆内部具有一些常用功能的组件,其中一个是处理渲染的组件。简化后,它看起来像这样:
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, () => '') }
}
虽然 TypeScript 对此设置不满意并表示:'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.
就个人而言,我看不到此参考。
作为一个可能的线索,如果我这样重写这段代码:
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, () => '') }
}
...一切正常,但我真的很想使用组件本身,因为现在还没有看到一些复杂的东西。
有什么问题吗?我可以用这个通用函数做点什么,这样 TypeScript 就不会争论了吗?
更新: 一些测试让我创建了一个更接近所需示例的示例:
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
函数是泛型的,而instance
类型依赖于泛型参数,所以TypeScript无法用合适的参数代替T
。有没有可能在不失去类型安全的情况下帮助他?
这里的问题似乎与渲染函数中实例参数的类型推断有关。
让我们看看
- 即使您将实例类型标记为 React.Component,当打字稿尝试推断渲染类型时,它也必须使用必须是 React.Component<> 的 'this' 实例,才能做到它也必须 ckech 渲染 class 成员,然后返回开始。所以我想打字稿决定放弃这个推论
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 实例参数标记为任意参数,以避免 typescript 推断再次检查实例。
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) }
}
我正在创建一堆内部具有一些常用功能的组件,其中一个是处理渲染的组件。简化后,它看起来像这样:
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, () => '') }
}
虽然 TypeScript 对此设置不满意并表示:'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.
就个人而言,我看不到此参考。
作为一个可能的线索,如果我这样重写这段代码:
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, () => '') }
}
...一切正常,但我真的很想使用组件本身,因为现在还没有看到一些复杂的东西。
有什么问题吗?我可以用这个通用函数做点什么,这样 TypeScript 就不会争论了吗?
更新: 一些测试让我创建了一个更接近所需示例的示例:
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
函数是泛型的,而instance
类型依赖于泛型参数,所以TypeScript无法用合适的参数代替T
。有没有可能在不失去类型安全的情况下帮助他?
这里的问题似乎与渲染函数中实例参数的类型推断有关。
让我们看看
- 即使您将实例类型标记为 React.Component,当打字稿尝试推断渲染类型时,它也必须使用必须是 React.Component<> 的 'this' 实例,才能做到它也必须 ckech 渲染 class 成员,然后返回开始。所以我想打字稿决定放弃这个推论
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 实例参数标记为任意参数,以避免 typescript 推断再次检查实例。
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) }
}