Typescript: konvertera arrayunion av ObjectId eller sträng till en array av strängar
Jag har en array foo av typen:
foo: ObjectId[] | string[];
Jag behöver tilldela det till en strängarray bar på följande sätt :
let bar : string[] = foo.map( (e) => e.toString())
Detta borde vara korrekt eftersom både ObjectID och string-typer har metoden toString() definierad. Dock kompileras inte ovanstående kod på grund av följande fel:
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.
Jag använder för närvarande följande lösning:
let bar : string[] = (foo as Array<string|ObjectID>).map( (e) => e.toString())
Finns det något bättre sätt att omvandla en array med blandade typer till sträng?
Svar #1
Tillåter foo.map()
Det kommer att fungera om du definierar foo med en signatur som säger "det är en array av strängar och ObjectIds, och också en array av antingen alla ObjectIds eller alla strängar". Detta känns löjligt eftersom den första delen antyds av den andra delen, men TypeScript fungerar inte på det sättet.
foo: (ObjectId | string)[] & (ObjectId[] | string[]);
Detta är bättre än att casta as (ObjectId | string)[] eftersom vi inte tappar informationen om att arrayen måste vara av en och samma typ. Men att ha (ObjectId | string)[] inkluderad som en del av typen innebär att det är okej att map:a.
Du kan göra detta till en utilitetstyp:
type ArrayOfEither<A, B> = (A | B)[] & (A[] | B[]);
Kartlägga foo genom en funktion
Om du inte kan ändra typen av foo, kan du göra din mappning i en separat funktion som tar foo som ett argument.
Detta fungerar eftersom den ursprungliga signaturen ObjectId[] | string[] är mycket specifik, men den kan tilldelas bredare typer som ArrayOfEither<ObjectId[], string[]> eller bara 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
Lekplatslänk
