Typescript - ... 没有兼容的调用签名

sle*_*mon 1 typescript reactjs

我收到不兼容的调用签名错误,不知道该怎么做才能使其正常工作。

反应状态

     this.state = {
    categoryState: ...,
    categoryItemId
    }
Run Code Online (Sandbox Code Playgroud)

类别声明

let category: Cat1[] | Cat2[] | Cat3[] = this.getCategory();
Run Code Online (Sandbox Code Playgroud)

getMethod 返回类别

private getCategory() {
        switch (this.state.categoryState) {
            case "Cat1": {
                return this.props.cat1 as Cat1[];
            }
            case "EVENT": {
                return this.props.cat2 as Cat2[];
            }
            default: {
                return this.props.cat3 as Cat3[];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

return-Method (react) 这是错误发生的地方:

<select value={this.state.categoryItemID} onChange={this.handleSomething}>
                                {(category && category.length > 0) &&
                                category.map((item: any) => {
                                    return (
                                        <option value={item.id}
                                                key={item.id}>{item.localizations[this.props.currentLanguage].title}</option>
                                    );
                                })
                                }
                            </select>
Run Code Online (Sandbox Code Playgroud)

错误消息:TS2349:无法调用类型缺少调用签名的表达式。类型 '((callbackfn: (value: Cat1, index: number, array: Cat1[]) => U, thisArg?: any) => U[] |...' 没有兼容的调用签名。

jca*_*alz 7

2019-03 更新:随着 TypeScript 3.3 的发布,在调用函数类型联合方面取得了进展,但不幸的是,这个痛点仍然存在于泛型方法中,例如Array.prototype.map()


这是一个痛点在打字稿:有没有办法来调用,除非“的功能类型union”要么他们接受完全相同的参数,或者在TS3.3开始,如果功能的联盟至多有一个元素是通用或超载. 在您的情况下,因为categoryis Cat1[] | Cat2[] | Cat3[],该方法category.map()本身就是参数不相同的泛型函数的联合;你不能这样称呼。调用category.map(f)iff是一个接受的函数应该是安全的Cat1 | Cat2 | Cat3(这似乎很明显,但涉及理解方法参数的逆变,这很容易混淆)。但是,正如链接问题所提到的,编译器不允许您这样做:

这是目前的设计,因为我们在获取联合类型的成员时不合成交叉调用签名——只有相同的调用签名出现在联合类型上。

所以你会得到一个错误。幸运的是有解决方法。在您的情况下,最简单的方法是category不将其视为Cat1[] | Cat2[] | Cat3[],而是将其视为(Cat1 | Cat2 | Cat3)[]。只要您只是从数组中读取而不是写入它,那么这样做就应该是安全的:

let category: Cat1[] | Cat2[] | Cat3[] = this.getCategory();
const mappableCategory = category as (Cat1 | Cat2 | Cat3)[];
Run Code Online (Sandbox Code Playgroud)

现在你应该能够映射mappableCategory而不是category

mappableCategory.map((item: any) => { /* ... */ }); // should work now.
Run Code Online (Sandbox Code Playgroud)

(重申一下:读取 frommappableCategory很好,但写入 tomappableCategory可能是一个错误,因为它会很乐意接受 的元素Cat1,即使底层category是 的数组Cat2。所以除非你确定你是什么,否则不要写入它'重新做。)

希望能帮到你。祝你好运!