You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在含联合类型元素的数组中正确使用find等数组方法?

Fixing Type 'A | B' is not assignable to type 'B' with Array.find() and Union Types

Great question—this is a super common gotcha when working with union types and array methods in TypeScript. Let’s break down why the error pops up, then walk through all your options (including way better alternatives to overriding the Array interface).

Why the Error Happens

Looking at the Array<T> interface you shared, there are two key overloads for find:

  • The first uses a type predicate (value is S) to narrow the return type to S | undefined.
  • The second uses a regular boolean predicate, which only tells TypeScript the result is T | undefined (in your case, A | B | undefined).

Your current code uses the second overload—even though your predicate checks instanceof B, TypeScript can’t infer from a boolean return alone that the matched element is definitely a B. So it sticks with the broader union type, causing the assignment error.

Better Solutions Than Overriding the Array Interface

Overriding the Array interface to return arbitrary S is risky because it throws out TypeScript’s type safety (you could incorrectly cast to any type, even if your predicate is wrong). Here are safer, idiomatic fixes:

Update your predicate to return a type predicate (el is B), which explicitly tells TypeScript: "when this function returns true, the element is a B". This triggers the first find overload, which correctly narrows the return type to B | undefined:

class A {}
class B { b: string = "example" } // Added required property for context
const arr = [new A(), new B()]

function findB(): B | undefined {
  return arr.find((el): el is B => el instanceof B)
}

This is the most type-safe approach—TypeScript will enforce that your predicate correctly identifies B instances, and the return type stays accurate. You can use the same pattern with filter too!

2. Non-Null Assertion (Only If You’re 100% Sure the Element Exists)

If you guarantee there’s always at least one B in the array, you can use the non-null assertion operator (!) to tell TypeScript to ignore the undefined case:

function findB(): B {
  return arr.find(el => el instanceof B)!
}

⚠️ Heads up: This bypasses type checks—if the array ever has no B instances, you’ll get a runtime error. Only use this when you’re absolutely certain the element exists.

3. Type Assertion (Use Sparingly)

You can explicitly assert the result is a B, which is more flexible if you want to handle undefined:

function findB(): B | undefined {
  const result = arr.find(el => el instanceof B)
  return result as B | undefined
}

Or, if you want to return B directly (again, only if you’re sure it exists):

function findB(): B {
  return arr.find(el => el instanceof B) as B
}

Like the non-null assertion, this puts the responsibility on you to ensure the type is correct—TypeScript won’t validate it for you.

Why Overriding the Array Interface Is a Bad Idea

The interface override you shared:

interface Array<T> {
  find<S>(predicate: (this: void, value: T, index: number, obj: T[]) => boolean, thisArg?: any): S | undefined;
}

Wipes out the type safety built into the original interface. You could now write arr.find(el => el instanceof A) as B and TypeScript wouldn’t bat an eye, even though that’s completely incorrect. This defeats the whole point of using TypeScript.

Summary

  • Best practice: Use a type predicate to let TypeScript correctly narrow the return type of find (and other array methods like filter).
  • Compromise options: Non-null assertions or type assertions work if you’re certain about the array contents, but carry runtime risk.
  • Avoid: Overriding the Array interface—it undermines TypeScript’s core purpose of keeping your code type-safe.

内容的提问来源于stack exchange,提问作者Ivan Semochkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:27:34