From 539a7a199cc12d1ad30c0d3f21af90770540954a Mon Sep 17 00:00:00 2001 From: Marlon Tucker Date: Wed, 20 May 2020 15:41:45 +0100 Subject: [PATCH] Fixing typings for promise return types --- src/child/connectToParent.ts | 8 ++++---- src/parent/connectToChild.ts | 8 ++++---- src/types.ts | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/child/connectToParent.ts b/src/child/connectToParent.ts index 1409ae6..430f203 100644 --- a/src/child/connectToParent.ts +++ b/src/child/connectToParent.ts @@ -1,6 +1,6 @@ import createDestructor from '../createDestructor'; import createLogger from '../createLogger'; -import { SynMessage, Methods, PenpalError, CallSender } from '../types'; +import { SynMessage, Methods, PenpalError, CallSender, AsyncMethodReturns } from '../types'; import { ErrorCode, MessageType, NativeEventType } from '../enums'; import validateWindowIsIframe from './validateWindowIsIframe'; import handleSynAckMessageFactory from './handleSynAckMessageFactory'; @@ -39,7 +39,7 @@ type Connection = { /** * A promise which will be resolved once a connection has been established. */ - promise: Promise; + promise: Promise>; /** * A method that, when called, will disconnect any messaging channels. * You may call this even before a connection has been established. @@ -73,7 +73,7 @@ export default (options: Options = {}): window.parent.postMessage(synMessage, parentOriginForSyn); }; - const promise: Promise = new Promise((resolve, reject) => { + const promise: Promise> = new Promise((resolve, reject) => { const stopConnectionTimeout = startConnectionTimeout(timeout, destroy); const handleMessage = (event: MessageEvent) => { // Under niche scenarios, we get into this function after @@ -92,7 +92,7 @@ export default (options: Options = {}): } if (event.data.penpal === MessageType.SynAck) { - const callSender = handleSynAckMessage(event) as TCallSender; + const callSender = handleSynAckMessage(event) as AsyncMethodReturns; if (callSender) { window.removeEventListener(NativeEventType.Message, handleMessage); stopConnectionTimeout(); diff --git a/src/parent/connectToChild.ts b/src/parent/connectToChild.ts index 8471161..737c613 100644 --- a/src/parent/connectToChild.ts +++ b/src/parent/connectToChild.ts @@ -3,7 +3,7 @@ import getOriginFromSrc from './getOriginFromSrc'; import createLogger from '../createLogger'; import handleSynMessageFactory from './handleSynMessageFactory'; import handleAckMessageFactory from './handleAckMessageFactory'; -import { CallSender, Methods, PenpalError } from '../types'; +import { CallSender, Methods, PenpalError, AsyncMethodReturns } from '../types'; import { ErrorCode, MessageType, NativeEventType } from '../enums'; import validateIframeHasSrcOrSrcDoc from './validateIframeHasSrcOrSrcDoc'; import monitorIframeRemoval from './monitorIframeRemoval'; @@ -39,7 +39,7 @@ type Connection = { /** * A promise which will be resolved once a connection has been established. */ - promise: Promise; + promise: Promise>; /** * A method that, when called, will disconnect any messaging channels. * You may call this even before a connection has been established. @@ -80,7 +80,7 @@ export default (options: Options): Conn log ); - const promise: Promise = new Promise((resolve, reject) => { + const promise: Promise> = new Promise((resolve, reject) => { const stopConnectionTimeout = startConnectionTimeout(timeout, destroy); const handleMessage = (event: MessageEvent) => { if (event.source !== iframe.contentWindow || !event.data) { @@ -93,7 +93,7 @@ export default (options: Options): Conn } if (event.data.penpal === MessageType.Ack) { - const callSender = handleAckMessage(event) as TCallSender; + const callSender = handleAckMessage(event) as AsyncMethodReturns; if (callSender) { stopConnectionTimeout(); diff --git a/src/types.ts b/src/types.ts index a1d2532..008ef22 100644 --- a/src/types.ts +++ b/src/types.ts @@ -89,3 +89,19 @@ export type CallSender = { * A Penpal-specific error. */ export type PenpalError = Error & { code: ErrorCode }; + +/** + * A mapped type to extract only object properties which are functions. + */ +export type FunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]; + +/** + * A mapped type to convert non async methods into async methods and exclude any non function properties. + */ +export type AsyncMethodReturns> = { + [KK in K]: T[KK] extends (...args: any[]) => PromiseLike + ? T[KK] + : T[KK] extends (...args: infer A) => infer R + ? (...args: A) => Promise + : T[KK] +};