You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Item 45: Hide Unsafe Type Assertions in Well-Typed Functions
Things to Remember
Sometimes unsafe type assertions and any types are necessary or expedient. When you need to use one, hide it inside a function with a correct signature.
Don't compromise a function's type signature to fix type errors in the implementation.
Make sure you explain why your type assertions are valid, and unit test your code thoroughly.
Code Samples
interfaceMountainPeak{name: string;continent: string;elevationMeters: number;firstAscentYear: number;}asyncfunctioncheckedFetchJSON(url: string): Promise<unknown>{constresponse=awaitfetch(url);if(!response.ok){thrownewError(`Unable to fetch! ${response.statusText}`);}returnresponse.json();}exportasyncfunctionfetchPeak(peakId: string): Promise<MountainPeak>{returncheckedFetchJSON(`/api/mountain-peaks/${peakId}`);// ~~~~~ Type 'unknown' is not assignable to type 'MountainPeak'.}
constsevenPeaks=['aconcagua','denali','elbrus','everest','kilimanjaro','vinson','wilhelm'];asyncfunctiongetPeaksByHeight(): Promise<MountainPeak[]>{constpeaks=awaitPromise.all(sevenPeaks.map(fetchPeak));returnpeaks.toSorted(// ~~~ Type 'unknown' is not assignable to type 'MountainPeak'.(a,b)=>b.elevationMeters-a.elevationMeters// ~ ~ 'b' and 'a' are of type 'unknown');}
asyncfunctiongetPeaksByContinent(): Promise<MountainPeak[]>{constpeaks=awaitPromise.all(sevenPeaks.map(fetchPeak));// no assertion!returnpeaks.toSorted((a,b)=>a.continent.localeCompare(b.continent));}
functionshallowObjectEqual(a: object,b: object): boolean{for(const[k,aVal]ofObject.entries(a)){if(!(kinb)||aVal!==b[k]){// ~~~~ Element implicitly has an 'any' type// because type '{}' has no index signaturereturnfalse;}}returnObject.keys(a).length===Object.keys(b).length;}
functionshallowObjectEqualGood(a: object,b: object): boolean{for(const[k,aVal]ofObject.entries(a)){if(!(kinb)||aVal!==(basany)[k]){// `(b as any)[k]` is OK because we've just checked `k in b`returnfalse;}}returnObject.keys(a).length===Object.keys(b).length;}