简体   繁体   中英

Typescript generic interface with union type

I want to use an interface with generic union types like this:

interface IOperator {
  <U>(a: U[], b: U[] | U): boolean
}

export const intersects: IOperator = (a, b) => a.some((el) => b.includes(el))
export const includes: IOperator = (a, b) => a.includes(b)

However, TS gives me error on both regarding one of the union types:

Property 'includes' does not exist on type 'U | U[]'.
  Property 'includes' does not exist on type 'U'.

How do I typecast properly here?

I tried:

export const intersects: IOperator = (a, b) => a.some((el) => (b as U[]).includes(el))

However, that gives me an error:

Cannot find name 'U'.

So how to handle generic union types?

I know that for the intersects method the types for input b should only be arrays and for the includes method the types for input b should never be arrays. The idea for the interface is to not repeat myself as I have plenty of methods where some require b to be an array and others to not be an array. I'd try to avoid to create two separate interfaces.

Thank you!

I think:

export const intersects: IOperator = (a, b) => a.some((el) => Array.isArray(b)&&b.includes(el))

should work. Otherwise, b might not be an Array of type U, so that includes is not available.

The issue with using casting here is if the value of B doesn't match your casting, you'll have a runtime error. That being said, your use case may be valid and we just don't have the context available to see it. Otherwise, you may want to do a runtime check as suggested by some of the comments to your post.

This solution uses function to give you access to U , and then assigns the function to a const so you can type check that your function signature matches your interface.

interface IOperator {
  <U>(a: U[], b: U[] | U): boolean
}

function _intersects <U>(a: U[], b: U[] | U): boolean {
  return a.some((el) => (b as U[]).includes(el));
}
export const intersects: IOperator = _intersects;

function _includes <U>(a: U[], b: U[] | U): boolean {
  return a.includes(b as U);
}
export const includes: IOperator = _includes;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM