代码之家  ›  专栏  ›  技术社区  ›  Vladyslav Zavalykhatko

无法调用其类型缺少调用签名、映射的表达式

  •  1
  • Vladyslav Zavalykhatko  · 技术社区  · 6 年前

    此代码有效:

    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 我有个错误:

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

    我做错什么了?

    如果classA如下所示,则该错误是可重复的:

    class classA {
        anyArg: number
    
        constructor(anyArg: number) {
            this.anyArg = anyArg
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  7
  •   jcalz    6 年前

    正如我在评论中提到的, 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 元素”,而后者是“这是一个元素数组,每个元素都是 甲级 或者 B类 ". 前者更具体,因为如果你知道 arr[0] 是一个 甲级 ,然后 arr[1] 也将是 甲级 ... 而后者则不那么具体,因为 arr[0] 可能是 甲级 虽然 阿瑞[1] 可能是 B类 . 后者的一个优点是 (classA | classB)[]['map'] 只有一个签名:

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

    和你 可以 就这样吧。


    你的下一个问题,“如果我在任何类中定义了什么,为什么它会停止工作”与 structural typing . 简而言之,TypeScript认为 甲级 B类 同一类型 如果他们有 相同的成员 . 这可能令人惊讶,因为许多其他类型的语言使用 nominal typing ,其中两种类型 姓名 一定是不同的类型。但TypeScript并不是这样工作的。

    如果 甲级 B类 都是空的,他们将被视为等同于 {} ,空类型。以及 (classA[])|(classB[]) 然后减少到 ({}[])|({}[]) 只是 ({}[]) . 那不是工会,所以你可以称之为工会 map 方法。

    如果你愿意 甲级 被视为不同于 B类 那么你应该 give them different properties ,至少直到(除非)TypeScript得到更一流的标称类型。


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