He tenido problemas para usar aserciones de tipo con múltiples tipos de retorno de promesa. Aquí hay una versión simplificada del código:
interface SimpleResponseType { key1: string }; interface SimpleResponseType2 { property1: string property2: number }; interface ServiceType { fetchResponse: () => Promise<SimpleResponseType | SimpleResponseType2> }; class Service implements ServiceType { async fetchResponse() { // code to fetch some api data and return some json // just return a pretend/sample response return { key1: 'json' }; }; }; const service = new Service(); await service.fetchResponse().then(resp => { // Should be typeof SimpleResponseType console.log(resp.key1) }) TypeScript subrayará la última key1 y arrojará este error:
Property 'key1' does not exist on type 'SimpleResponseType2'.ts(2339)Lo cual tiene sentido, pero cuando intento afirmar el tipo, aparecen más errores. Por ejemplo afirmarlo así:
await service.fetchResponse().then((resp as SimpleResponseType) => {Lanza este error:
Argument of type 'SimpleResponseType' is not assignable to parameter of type '(value: SimpleResponseType | SimpleResponseType2) => SimpleResponseType | SimpleResponseType2 | PromiseLike<...>'. Type 'SimpleResponseType' provides no match for the signature '(value: SimpleResponseType | SimpleResponseType2): SimpleResponseType | SimpleResponseType2La única afirmación que puedo hacer funcionar es así:
const respTyped = resp as SimpleResponseType Y luego use respTyped en lugar de resp .
Tal vez hay una mejor manera de lograr esto?
Potencialmente podría usar sobrecargas . Pero necesitaría tener diferentes parámetros de entrada en la función. No conozco su caso específico, pero parece un poco extraño que pueda haber dos tipos de devolución diferentes para la misma llamada de API/función exacta.
Editar: puede probar algo como esto, si desea usar la misma función para múltiples rutas API.
interface SimpleResponseType { key1: string }; interface SimpleResponseType2 { property1: string property2: number }; type SimpleResponseType3 = Array<SimpleResponseType2>; enum Routes { Route1 = "/api/route1", Route2 = "/api/route2", RouteWParam = "/api/route2/:id" } class Service { async fetchResponse(route: Routes.Route1) : Promise<SimpleResponseType>; async fetchResponse(route: Routes.Route2) : Promise<SimpleResponseType2>; async fetchResponse(route: Routes.RouteWParam, params: { id: number }) : Promise<SimpleResponseType3>; async fetchResponse(route: Routes, params?: Record<string, string | number>) { let url : string = route; if (params !== undefined) { //replace all params with the params passed url = Object.entries(params).reduce((previousValue: string, [param, value]) => { return previousValue.replace(`:${param}`, '' + value) }, route); } // You do lose type-safety inside this function. TS doesn't care if route is `Route1` and you try to return `SimpleResponseType2`. // That's up to you to make sure. const data = { key1: 'sdf' } const data2 = { property1: 'val', property2: 345 }; return new Promise((res) => { setTimeout(() => res(data2), 100) }) }; };No está del todo claro lo que pretende lograr, pero tal vez sea esto lo que pretende. Escriba fuertemente su tipo de servicio para que sepa el tipo de respuesta preciso.
interface SimpleResponseType { key1: string }; interface SimpleResponseType2 { property1: string property2: number }; interface ServiceType<T extends SimpleResponseType | SimpleResponseType2> { fetchResponse: () => Promise<T> }; class Service implements ServiceType<SimpleResponseType> { async fetchResponse() { // code to fetch some api data and return some json // just return a pretend/sample response return { key1: 'json' }; }; }; const service = new Service(); export {} await service.fetchResponse().then(resp => { // Should be typeof SimpleResponseType console.log(resp.key1) })return { key1 = 'json' };Parece que estás haciendo algo extraño. ¿Qué pasa si escribes:
return { key1: 'json' };