Mam więc opakowanie dla wywołań API do serwera strapi

export const api = {
    post: async<T extends unknown, K>(url: string, body: Partial<T>, jwt?: string): Promise<K> => {
        try {
            const result = await postData<Partial<T>, K>(url, body, jwt);
            return result;
        } catch (e) {
            throw e;
        }
    },
};

Próbuję to uzyskać, więc K jest opcjonalne, więc mogę wykonać następujące czynności

 await api.post<type1, type2>(url, body);
 await api.post<type1>(url, body);

Próbowałem

export const api = {
    post: async<T extends unknown, K = undefined>(url: string, body: Partial<T>, jwt?: string): Promise<K | T> => {
        try {
            const result = await postData<Partial<T>, K | T>(url, body, jwt);
            return result;
        } catch (e) {
            throw e;
        }
    },
};

Ale albo dostałbym błędy wpisywania, ponieważ brakowałoby pola z type1, gdy typ zwracany powinien być tylko type2, albo dostałbym, że obiekt zwracany może być prawdopodobnie niezdefiniowany.

Zastanawiałem się, czy jest to możliwe, więc jeśli oba typy są używane w funkcji post, użyje drugiego typu jako typu zwracanego lub użyje pierwszego typu jako typu zwracanego?

Pełny przykład, który można wkleić do placu zabaw maszynopisu z komentarzami, w których wystąpiły błędy

const api = {
    post: async<T extends unknown, K = undefined>(url: string, body: Partial<T>, jwt?: string): Promise<K | T> => {
        try {
            const result = await postData<Partial<T>, K | T>(url, body, jwt);
            return result;
        } catch (e) {
            throw e;
        }
    },
};

function postData<K, T>(url: string, data: K, jwt: string = '', failOnNotOk: boolean = true): T {
    const request: T = (data) as any;

    return request;
}

type user = {
    email: string;
    password: string;
}

type res = {
    valid: string;
}
(async () => {
    const url: string = 'https://google.com';
    const body: user = {
        email: 'test@example.com',
        password: 'test1234',
    };
    // this gives an error about result having the possibility of being undefined
    const result = await api.post<user>(url, body);
    console.log(result.email);

    // returns an errror about valid not being a field on user when the return type should only be res
    const res = await api.post<user, res>(url, body);
    console.log(res.valid);
})();
0
Justin_Nicholls 2 styczeń 2020, 21:36

1 odpowiedź

Najlepsza odpowiedź

Z przykładem jak podano, prawdopodobnie zmieniłbym to api.post do tego:

const api = {
    post: async<T extends unknown, U = T>(
      url: string, 
      body: Partial<T>, 
      jwt?: string
    ): Promise<U> => {
        try {
            const result = await postData<Partial<T>, U>(url, body, jwt);
            return result;
        } catch (e) {
            throw e;
        }
    },
};

(Zmieniłem się K do U, ponieważ nazwa K zazwyczaj implikuje właściwości przypisywane do keyof any). Tutaj typ powrotu będzie tylko Promise<U>, a U domyślnie jest to T, jeśli nie zostanie określony. Który daje następujące zachowanie:

const result = await api.post<user>(url, body);
console.log(result.email); // okay
const res = await api.post<user, res>(url, body);
console.log(res.valid); // okay

Które myślę, że chcesz. Należy pamiętać, że jest to trochę denerwujące, aby uzyskać wyraźnie określić user Maszynozkładnik nie ma bezpośredniego wsparcia dla Wnioskowanie parametru częściowego, więc nie ma możliwości po prostu mieć Kompilator wniosek T prawidłowo, jeśli chcesz również wyraźnie określić U / A> niekoniecznie lepiej niż tylko ręcznie określając T.

W każdym razie, mam nadzieję, że to pomoże; powodzenia!

Link do kodu placu zabaw

0
jcalz 2 styczeń 2020, 20:01