Narrow argument type to the specific event being listened to (#16714)

This commit is contained in:
Hariom Balhara authored and GitHub committed 2024-09-19 09:42:32 +00:00
1 parent 3ae53a4b6e
commit 6d133c26f8
7 files changed
+71 -12

No files matched your search

+25 -6
View File
@@ -1,7 +1,8 @@
import type { GlobalCal } from "./src/embed";
import type { GlobalCal, EmbedEvent } from "./src/embed";
const Cal = window.Cal as GlobalCal;
const callback = function (e) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const callback = function (e: any) {
const detail = e.detail;
console.log("Event: ", e.type, detail);
};
@@ -27,6 +28,7 @@ const only = searchParams.get("only");
const colorScheme = searchParams.get("color-scheme");
const prerender = searchParams.get("prerender");
// @ts-expect-error We haven't defined ENABLE_FUTURE_ROUTES as it is a playground specific variable.
window.ENABLE_FUTURE_ROUTES = searchParams.get("future-routes") === "true";
if (colorScheme) {
@@ -469,10 +471,6 @@ if (only === "all" || only == "ns:monthView") {
},
}
);
Cal.ns.monthView("on", {
action: "*",
callback,
});
}
if (only === "all" || only == "ns:weekView") {
@@ -532,3 +530,24 @@ if (only === "all" || only == "ns:columnView") {
callback,
});
}
// Verifies that the type of e.detail.data is valid. type-check will fail if we accidentally break it.
const bookingSuccessfulV2Callback = (e: EmbedEvent<"bookingSuccessfulV2">) => {
const data = e.detail.data;
console.log("bookingSuccessfulV2", {
endTime: data.endTime,
startTime: data.startTime,
title: data.title,
});
// Remove the event listener after it is fired once
Cal("off", {
action: "bookingSuccessfulV2",
callback: bookingSuccessfulV2Callback,
});
};
Cal("on", {
action: "bookingSuccessfulV2",
callback: bookingSuccessfulV2Callback,
});
+17 -3
View File
@@ -10,6 +10,10 @@ import allCss from "./tailwind.generated.css?inline";
import type { UiConfig } from "./types";
export type { PrefillAndIframeAttrsConfig } from "./embed-iframe";
// Exporting for consumption by @calcom/embed-core user
export type { EmbedEvent } from "./sdk-action-manager";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Rest<T extends any[]> = T extends [any, ...infer U] ? U : never;
export type Message = {
@@ -141,10 +145,20 @@ function withColorScheme(
return queryObject;
}
type allPossibleCallbacksAndActions = {
[K in keyof EventDataMap]: {
action: K;
callback: (arg0: CustomEvent<EventData<K>>) => void;
};
}[keyof EventDataMap];
type SingleInstructionMap = {
// TODO: This makes api("on", {}) loose it's generic type. Find a way to fix it.
// e.g. api("on", { action: "__dimensionChanged", callback: (e) => { /* `e.detail.data` has all possible values for all events/actions */} });
[K in keyof CalApi]: CalApi[K] extends (...args: never[]) => void ? [K, ...Parameters<CalApi[K]>] : never;
on: ["on", allPossibleCallbacksAndActions];
off: ["off", allPossibleCallbacksAndActions];
} & {
[K in Exclude<keyof CalApi, "on" | "off">]: CalApi[K] extends (...args: never[]) => void
? [K, ...Parameters<CalApi[K]>]
: never;
};
type SingleInstruction = SingleInstructionMap[keyof SingleInstructionMap];
@@ -117,6 +117,8 @@ export type EventData<T extends keyof EventDataMap> = {
};
}[T];
export type EmbedEvent<T extends keyof EventDataMap> = CustomEvent<EventData<T>>;
export class SdkActionManager {
namespace: Namespace;
+1 -1
View File
@@ -12,6 +12,6 @@
"@calcom/embed-snippet": ["../embed-snippet/src"]
}
},
"include": ["src", "env.d.ts", "index.ts"],
"include": ["src", "env.d.ts", "index.ts", "*.ts"],
"exclude": ["dist", "build", "node_modules"]
}
+22 -1
View File
@@ -8,7 +8,7 @@ import ReactDom from "react-dom";
// Because we don't import from @calcom/embed-react, this file isn't able to test if the build is successful or not and thus npm package would work or not correctly.
// There are tests in test/built which verifiy that the types from built package are correctly generated and exported correctly.
import Cal, { getCalApi } from "./src/index";
import Cal, { getCalApi, type EmbedEvent } from "./src/index";
const api = getCalApi({
namespace: "inline",
@@ -49,6 +49,27 @@ function App() {
action: "*",
callback,
});
// Also, validates the type of e.detail.data as TS runs on this file
const bookingSuccessfulV2Callback = (e: EmbedEvent<"bookingSuccessfulV2">) => {
const data = e.detail.data;
console.log("bookingSuccessfulV2", {
endTime: data.endTime,
startTime: data.startTime,
title: data.title,
});
// Remove the event listener after it is fired once as I don't need it.
api("off", {
action: "bookingSuccessfulV2",
callback: bookingSuccessfulV2Callback,
});
};
api("on", {
action: "bookingSuccessfulV2",
callback: bookingSuccessfulV2Callback,
});
});
};
}, []);
+3
View File
@@ -5,6 +5,9 @@ import EmbedSnippet from "@calcom/embed-snippet";
import Cal from "./Cal";
// Exporting for consumption by @calcom/embed-react user
export type { EmbedEvent } from "@calcom/embed-core";
export function getCalApi(options?: {
embedJsUrl?: string;
namespace?: string;
+1 -1
View File
@@ -13,7 +13,7 @@
"@calcom/embed-snippet": ["../embed-snippet/src"]
}
},
"include": ["src/**/*.ts", "src/**/*.tsx", "env.d.ts"],
"include": ["src/**/*.ts", "src/**/*.tsx", "env.d.ts", "*.tsx", "*.ts"],
// Exclude "test" because that has `api.test.ts` which imports @calcom/embed-react which needs it to be built using this tsconfig.json first. Excluding it here prevents type-check from validating test folder
"exclude": ["node_modules", "test"]
}