it is similar question to TypeScript function return type based on input parameter but i don't understand how it works with promises. input is string or string[] if is string then method returns PlaylistEntity else array of them
type TypeName = string | string[]
type ObjectType<T> = Promise<T extends string ? PlaylistEntity : PlaylistEntity[]>
async get<T extends TypeName>(playlists: T): ObjectType<T>{
try {
const col = collection(firestore, 'playlists')
if(Array.isArray(playlists)){
const fetchArray = playlists.slice(0, 10)
const q = query(col, where('__name__', 'in', fetchArray))
const docs = await getDocs(q)
return docs.docs.map(v => {return {id: v.id, ...v.data()} as PlaylistEntity})
}
else{
const docRef = await getDoc(doc(col, playlists))
return {id: docRef.id, ...docRef.data()} as PlaylistEntity
}
}catch (e) {
throw new HttpException(e.message, HttpStatus.INTERNAL_SERVER_ERROR)
}
}
error TS2322: Type 'PlaylistEntity' is not assignable to type 'T extends string ? PlaylistEntity : PlaylistEntity[]'.
43 return {id: docRef.id, ...docRef.data()} as PlaylistEntity
CodePudding user response:
Maybe function overloads can help you with modeling your TS types?
// Some dummy interface.
interface PlaylistEntity {
id: string
};
// When caller passes string[], returned promise resolves to PlaylistEntity[].
async function getPlaylistEntries(playlists: string[]): Promise<PlaylistEntity[]>;
// When caller passes string, returned promise resolves to PlaylistEntity.
async function getPlaylistEntries(playlists: string): Promise<PlaylistEntity>;
// Single implementation satisfying both overloads.
async function getPlaylistEntries(playlists: string | string[]) {
try {
if (Array.isArray(playlists)){
return playlists.map((p: string) => ({id: "some-id"}));
}
else{
return {id: "some-id"};
}
}catch (e) {
throw new Error();
}
}
// onePlaylistEntry inferred type is Promise<PlaylistEntity>
const onePlaylistEntry = getPlaylistEntries("a")
// arrOfPlayListEntries inferred type is Promise<PlaylistEntity[]>
const arrOfPlayListEntries = getPlaylistEntries(["a"])
Check ^this in TS playground.