Scenario
You are using a function called doFunkyStuff
from a library called funky-lib
. Do doFunkyStuff
returns an interface FunkyStuff
, but funky-lib
does not export FunkyStuff
The lib code
// node_modules/funcky-lib/index.ts interface FunkyStuff { message: string, funkinessLevel: number } export function doFunkyStuff(): FunkyStuff { console.log('doing funky stuff') return { message: 'did some funky stuff', funkinessLevel: Math.random(), } }
Our Code
// index.ts import { doFunkyStuff } from 'funky-stuff' // eslint yells no-explicit-any function repeatFunkyStuff(fStuff: any) { console.log('repeating funky stuff', fStuff) return {...fStuff} } repeatFunkyStuff(doFunkyStuff)
Depending on your eslint-config, eslint would either yell "no-implicit-any" or "no-explicit-any"
Bad Solution
Redefine FunkyStuff
function repeatFunkyStuff(fStuff: { message: string; funkinessLevel: number})
The solution above is bad because it becomes unreadable if FunkyStuff
has more than a handful of properties.
Also, we must update our code each time something changes in FunkyStuff
.
Good solution
Use the ReturnType
utility type.
// our code in index.ts ... type AppFunkyStuff = ReturnType<typeof doFunkyStuff> function repeatFunkyStuff(fStuff: AppFunkyStuff) { ... } ...
Bonus
You can combine ReturnType<T>
with Awaited<T>
util type for functions that return promises.
Assuming doFunkyStuff
returns Promise, then AppFunkyStuff
would be defined like this.
type AppFunkyStuff = Awaited<ReturnType<typeof doFunkyStuff>>
⚠️ Awaited util became only available in typescript 4.5. Achieving the same effect can be a little tricky. Previous versions
Summary
This tip is just the tip of the iceberg regarding what typescript offers.
Top comments (0)