typescript 对具有两种可能数组类型的值调用find()时出现“这些签名都不兼容”错误

vawmfj5a  于 2023-02-25  发布在  TypeScript
关注(0)|答案(3)|浏览(311)

下面是我尝试在打印脚本编辑器中运行的代码

type ABC = {
      title: string
  }

  type DEF = {
      name: string
  }

  type XYZ = {
      desc: ABC[] | DEF[]
  }

const container: XYZ = {
    desc: [{title: 'abc'},{title: 'def'}]
}
  const { desc } = container

desc.find((t: ABC) => t.title === 'abc')

但是find()下面有一条红线,当我将鼠标悬停在上面时,我看到了以下消息:

This expression is not callable.Each member of the union type 
'{ <S extends ABC>(predicate: (this: void, 
value: ABC, index: number, obj: ABC[]) => value is S, thisArg?: any): S | 
undefined; (predicate: (value: ABC, index: number, obj: ABC[]) => unknown, 
thisArg?: any): ABC | undefined; } | { ...; }' has signatures, but none of
 those signatures are compatible with each other.

我该如何修正这个问题,这样我就看不到曲线了

uhry853o

uhry853o1#

存在 * 两个 * 问题:一个是你的,一个是打字员的

  1. desc的类型是ABC[] | DEF[](如果您使用和IDE,它应该会告诉您这一点)。这意味着,为了实现类型安全,您需要提供一个find predicate ,该 predicate 可以处理ABC | DEF类型的元素,而不仅仅是您所拥有的ABC类型的元素。
    例如,这将是类型安全的:
desc.find((t: ABC | DEF) => 'title' in t && t.title === 'abc')

1.即使你提供了类型安全的 predicate find,Typescript目前也无法将其识别为类型安全的。

变通方案

由于您不清楚这一点,也没有回答我的问题,我将假设您的代码的意图是只找到具有正确标题的ABC元素,并忽略DEF元素,即使它们的name属性匹配"abc"。

快速破解

非类型安全的解决方法是硬编码类型Assert:

// This isn't type-safe, but it will still do "the right thing"
// at runtime even if desc is really a DEF[], because t.title
// will be undefined for DEF elements.
(desc as ABC[]).find((t: ABC) => t.title === 'abc')

类型安全解决方案

类型安全的解决方法是在对desc应用find predicate 之前,确保它实际上是ABC[]而不是DEF[]

type ABC = {
    title: string
}

type DEF = {
    name: string
}

type XYZ = {
    desc: ABC[] | DEF[]
}

const container: XYZ = {
    desc: [{ title: 'abc' }, { title: 'def' }]
}
const { desc } = container

let result: ABC | undefined

// only do the search if desc is an ABC[]
if (desc[0] && 'title' in desc[0]) {
    // Typescript isn't smart enough to figure out that
    // desc is now guaranteed to be an ABC[], we need
    // to include a type assertion
    result = (desc as ABC[]).find((t: ABC) => t.title === 'abc')
}

console.log(result)

您也可以在TS Playground中进行测试。

v1uwarro

v1uwarro2#

我是这样解决的

const { desc}: { desc: ABC[] } = container

desc.find((t: ABC) => t.title === 'abc')
brccelvz

brccelvz3#

可以在容器XYZ上使用模板化类型,因为在执行查找时,似乎要Assertdesc的类型为ABC[]

type ABC = {
    title: string
}

type DEF = {
    name: string
}

type XYZ<T extends ABC[] | DEF[]> = {
    desc: ABC[] | DEF[]
}

const container: XYZ<ABC[]> = {
    desc: [{title: 'abc'},{title: 'def'}]
}

const { desc } = container

desc.find((t: ABC) => t.title === 'abc')

相关问题