首页 > 解决方案 > typeof variable === "function" 为真,但由于意外的类型合并,变量仍然缺少调用签名

问题描述

非常类似于 React 我想在自定义库中使用状态,我目前有以下类:

export abstract class Room<State> {
    protected state: State;

    protected setState<Key extends keyof State>(
        state: ((previousState: Readonly<State>) => Pick<State, Key> | State)
             | (Pick<State, Key> | State)
    ) {
        if (typeof state === "function") {
            // Cannot invoke an expression whose type lacks a call signature. Type
            // '((previousState: Readonly<State>) => State | Pick<State, Key>) | (State & Function)'
            // has no compatible call signatures.
            const newState = state(this.state);
            // ...
        }
        // ...
    }
    // ...
}

正如您在评论中看到的那样,Typescript 抱怨 state 缺少调用签名,尽管我希望能够区分 state 参数的两种类型。令人惊讶的是,在它工作| State的类型末尾删除 final 时state,VS Code 中的 Intellisense 不再提供诸如this.setState({ foo: 1 });.

为什么 Typescript 会合并第二种类型的stateto State & Function?是否可以安全地重写它?

标签: typescript

解决方案


希望这会有所帮助,首先这里发生了一些事情,额外的括号什么都不做,因为联合是可交换的意思 A | (B | C) 与 (A | B) | 相同 C 基本上括号没有任何意义,其次要解决函数问题,只需编写 typeof state !== "object" 意味着你从联合中摆脱了 2/3,只剩下函数。希望这可以帮助

export abstract class Room<State extends object> {
    protected state: State = "" as any;

    protected setState<Key extends keyof State>(
        state: ((previousState: Readonly<State>) => Pick<State, Key> | State) | (Pick<State, Key>) | State
    ) {
        if (typeof state !== "object") {
            const newState = state(this.state);
        }
    }
}

抱歉编辑,它失败的原因是因为当打字稿一般解释它时,对 State 含义没有通用约束,它不能假设 State 不是函数,这意味着 typeof state === "function" 可能会给你留下任何类型状态是。


推荐阅读