簡體   English   中英

打字稿:使用接受組件實例的外部函數來響應渲染

[英]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不會爭論嗎?


UPD:經過一些測試,讓我創建了一個更接近所需示例的示例:

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代替適當的參數。 是否可以在不失去類型安全性的情況下幫助他?

這里的問題似乎與render函數中實例參數的類型推斷有關。

讓我們來看看

  • 即使您將實例類型標記為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) }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM