Reputation: 1045
I have an array foo
of the type:
foo: ObjectId[] | string[];
I need to assign it to a string array bar
as follows :
let bar : string[] = foo.map( (e) => e.toString())
This should be correct since both ObjectID
and string
types have toString()
method defined. However the above code is not compiled because of the following error :
This expression is not callable.
Each member of the union type '(<U>(callbackfn: (value: ObjectId, index: number, array: ObjectId[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[])' has signatures, but none of those signatures are compatible with each other.
I am currently using the following workaround :
let bar : string[] = (foo as Array<string|ObjectID>).map( (e) => e.toString())
Is there some better way to cast the array of mixed type to string?
Upvotes: 4
Views: 375
Reputation: 42228
It will work if you define foo
with a signature that says "it's an array of strings and ObjectIds, and also it's an array of all ObjectIds or all strings". This feels silly because the first part is implied by the second part, but typescript doesn't work that way.
foo: (ObjectId | string)[] & (ObjectId[] | string[]);
This is better than casting as (ObjectId | string)[]
because we don't lose the information that the array has to be all of one type. But having the (ObjectId | string)[]
included as part of the type means that it's ok to map.
You can make this into a utility type:
type ArrayOfEither<A, B> = (A | B)[] & (A[] | B[]);
If you can't change the type of foo
, then you can do your mapping in a separate function which takes foo
as an argument.
This works because the original signature ObjectId[] | string[]
is very specific, but it's assignable to broader types like ArrayOfEither<ObjectId[], string[]>
or just Stringable[]
.
interface Stringable {
toString(): string;
}
const myFunction = ( array: Stringable[] ): string[] => {
return array.map(e => e.toString());
}
declare const foo: ObjectId[] | string[];
myFunction(foo); // no errors
Upvotes: 1