无法调用类型缺少呼叫签名,地图的表达式

时间:2018-07-28 13:10:21

标签: typescript

此代码有效:

class A {}
class B {}
class C {}

const classCFromAOrB = (element: A | B): C => new C()

const a: A[] | B[] = [new A()]

const c: C[] = a.map(element => classCFromAOrB(element))

此代码不:

import { classA } from '../some'
import { classB } from './../some'

interface interfaceC {}

const render = (element: classA | classB): interfaceC => {
    return {}
}

interface ResultsScreenProps {
    resultsScreenPresented: boolean
    answers: classA[] | classB[]
    dismiss: SimpleFunc
}

const Screen: React.SFC<ResultsScreenProps> = (props) => {
    const array: classA[] | classB[] = props.answers
    const second: interfaceC[] = array.map(el => render(el)) // here is the error
    ...
}

在定义second的行上出现错误:

  

[ts]无法调用类型缺少调用签名的表达式。   类型'(((callbackfn:(值:classA,索引:数字,数组:classA [])   => ...'没有兼容的呼叫签名。

我在做什么错了?

如果classA看起来像这样,则该错误是可重现的:

class classA {
    anyArg: number

    constructor(anyArg: number) {
        this.anyArg = anyArg
    }
}

1 个答案:

答案 0 :(得分:4)

正如我在评论中所述,you can't call methods which are union types(classA[] | classB[])['map']的呼叫签名为

(
  <U>(
    callbackfn: (value: classA, index: number, array: classA[]) => U,
    thisArg?: any
  ) => U[]
) | (
  <U>(
    callbackfn: (value: classB, index: number, array: classB[]) => U,
    thisArg?: any
  ) => U[]
)

然后编译器放弃了。您可以做的是将类型从(classA[] | classB[])扩展到(classA | classB)[]。前者是“这是所有classA元素的数组,或者是所有classB元素的数组”,而后者是“这是元素的数组,每个元素都是一个classAclassB”。前者更具体,因为如果您知道arr[0]classA,那么arr[1]也将是classA ...而后者则较不具体,因为{ {1}}可以是arr[0],而classA可以是arr[1]。后者的优点是classB具有单个签名:

(classA | classB)[]['map']

可以调用它。


您的下一个问题,“如果我在任何类中定义任何内容,为什么它会停止工作”与structural typing有关。简而言之,TypeScript认为<U>( callbackfn: (value: classA | classB, index: number, array: (classA | classB)[]) => U, thisArg?: any ) => U[] classA如果具有相同的成员,则它们是相同的类型。这可能令人惊讶,因为许多其他类型的语言都使用nominal typing,其中两个具有不同 names 的类型必然是不同的类型。但是TypeScript并不是真的那样工作。

如果classBclassA都没有属性,那么它们将被视为等同于classB(空类型)。然后{}减少为(classA[])|(classB[])的{​​{1}}。那不是联合,所以您可以调用其({}[])|({}[])方法。

如果您希望编译器将({}[])map区别开,那么您应该give them different properties,至少直到(并且除非)TypeScript获得更多的一等标称值


希望对您有帮助。祝你好运。