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
You can filter only the fulfilled promises from a Promise.allSettled call, which also infers the types of the fulfilled promises
typeExtractFulfilled<TextendsPromiseSettledResult<any>[]>=Extract<T[number],PromiseFulfilledResult<any>>['value'];functionfilterFulfilled<TextendsArray<PromiseSettledResult<any>>>(settled: T): Array<ExtractFulfilled<T>>{constfulfilled=settled.filter((result): result is PromiseFulfilledResult<any>=>'status'inresult&&result.status==='fulfilled');constfulfilledValues=fulfilled.map((result)=>result.value);returnfulfilledValues;}constsettled=awaitPromise.allSettled([Promise.resolve('foo'),Promise.resolve(123),Promise.reject(newError('nope'))]);constfulfilledPromises=filterFulfilled(settled);// You could use something like zod to find/filter the correct item types from the array of fulfilled promisesconstfoo=fulfilledPromises.find((foo): foo is string=>typeoffoo==='string');
Infer the value of an unamed type using infer and conditional types.
Useful for when a type isn't exported by a library/component. But be aware, this will start to slow the compiler and linter down if used excessively.
typeConstructorArgs<C>=Cextends{// "infer A" allows us to alias the type of the unknown constructor argnew(arg: infer A, ...args: any[]): any;// Find the "newable" function, i.e. constructor}
? A
: never;classClassWithUnknownConstructorArgs{constructor(arg: {foo?: string;bar?: number}){// ...}}// Now we can use the ConstructorArgs utility type to find out what constconstructorArgs: ConstructorArgs<typeofClassWithUnknownConstructorArgs>={foo: '',notAPropertyOnConstructorArgsType: false// This line will error because the type is now known};constinstance=newClassWithUnknownConstructorArgs(constructorArgs);
Typeguard
Make sure condition returns the asserted type. The operative thing here is the the return type : valueToTest is Car which effectively casts the type of the variable when used inside the condition.
typeCar={make: string;model: string;year: number;};letpossibleCar: unknown;// The boolean returned here is interpreted by TypeScript to respect the claim made by the result of the conditionfunctionisCar(valueToTest: any): valueToTest is Car{return(valueToTest&&typeofvalueToTest==='object'&&'make'invalueToTest&&typeofvalueToTest.make==='string'&&'model'invalueToTest&&typeofvalueToTest.model==='string'&&'year'invalueToTest&&typeofvalueToTest.year==='number');}if(isCar(possibleCar)){// `possibleCar` will now be considered to be a type of Car when referenced inside this conditionpossibleCar.make// Casting to a Car is no longer necessary(possibleCarasCar).make}
Another instance where typeguards can be used is within a filter to assert the types of the array items. Example taken from here
interfaceMyItem{name: string}constmyItems: (MyItem|undefined)[]=[{name: 'c'},{name: 'b'},undefined,{name: 'a'},]// a and b will always be "possibly 'undefined'"myItems.sort((a,b)=>(a.name>b.name ? 1 : -1));// (parameter) a: MyItem | undefined// Object is possibly 'undefined'// Chaining a filter before the sort ensures a and b will always be a type of MyItemmyItems.filter((item): item is MyItem=>!!item).sort((a,b)=>(a.name>b.name ? 1 : -1));
Template Literal Types
Combine types together with template literal string interpolation. Can also transform strings using Uppercase, Lowercase, Capitalize and Uncapitalize (Intrinsic String Manipulation Types).
typeAnimals=keyoftypeofanimalFoodMap;exporttypeAnimalFood={[AnimalinAnimals]: AnimalextendsAnimals
? `${Capitalize<Animal>}s like to eat ${(typeofanimalFoodMap)[Animal]}`
: never;}[Animals];exportconstanimalFoodMap={elephant: "Acacia leaves and grasses",koala: "Eucalyptus leaves",orca: "Salmon",}asconst;exportfunctiongetAnimalFood<TextendsAnimals>(animal: T): (typeofanimalFoodMap)[T]{returnanimalFoodMap[animal];}exportconstelephantFood: AnimalFood=`Elephants like to eat ${getAnimalFood("elephant")}`;exportconstkoalaFood: AnimalFood=`Koalas like to eat ${getAnimalFood("koala")}`;exportconstorcaFood: AnimalFood=`Orcas like to eat ${getAnimalFood("orca")}`;