Home > Software design >  function return type based on input type
function return type based on input type

Time:06-15

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.

  • Related