/** * TypeScript utility types for verifying that two interfaces have matching method signatures. * * This is particularly useful for ensuring that typed and untyped versions of interfaces * stay in sync when one has generics and the other doesn't. * * @example * ```typescript * import type { InterfaceAssertion } from "./InterfaceVerification"; * * interface BaseModule extends HybridObject<{ ios: "swift" }> { * getData(id: string): Promise; * } * * interface BaseModuleTyped { * getData(id: T): Promise; * } * * // This will cause a TypeScript error if the interfaces don't match * const _verification: InterfaceAssertion = true; * ``` */ /** * Extracts method names from an interface, excluding specified keys */ export type ExtractMethodNames = Exclude; /** * Gets the parameter count of a function type */ export type GetParameterCount = T extends (...args: infer P) => unknown ? P['length'] : never; /** * Checks if two interfaces have the same method names */ export type CheckMethodNames = { BaseMethodNames: ExtractMethodNames; TypedMethodNames: ExtractMethodNames; MissingInBase: Exclude, ExtractMethodNames>; MissingInTyped: Exclude, ExtractMethodNames>; InterfaceMismatch: Exclude, ExtractMethodNames> | Exclude, ExtractMethodNames>; }; /** * Checks parameter counts for shared methods between two interfaces */ export type CheckParameterCounts = { SharedMethodNames: ExtractMethodNames & ExtractMethodNames; ParameterCountMismatches: { [K in ExtractMethodNames & ExtractMethodNames]: GetParameterCount extends GetParameterCount ? GetParameterCount extends GetParameterCount ? never : K : K; }[ExtractMethodNames & ExtractMethodNames]; }; /** * Checks that typed methods remain assignable to their base counterparts. */ export type CheckMethodCompatibility = { SharedMethodNames: ExtractMethodNames & ExtractMethodNames; IncompatibleMethods: { [K in ExtractMethodNames & ExtractMethodNames]: TypedInterface[K] extends BaseInterface[K] ? never : K; }[ExtractMethodNames & ExtractMethodNames]; }; /** * Complete interface verification that checks both method names and parameter counts */ export type VerifyInterfaceSync = { MethodCheck: CheckMethodNames; ParameterCheck: CheckParameterCounts; CompatibilityCheck: CheckMethodCompatibility; Result: CheckMethodNames['InterfaceMismatch'] extends never ? CheckParameterCounts['ParameterCountMismatches'] extends never ? CheckMethodCompatibility['IncompatibleMethods'] extends never ? true : { ERROR: 'Method signature compatibility mismatch detected'; IncompatibleMethods: CheckMethodCompatibility['IncompatibleMethods']; } : { ERROR: 'Parameter count mismatch detected'; MethodsWithParameterCountMismatch: CheckParameterCounts['ParameterCountMismatches']; } : { ERROR: 'Interface mismatch detected'; MissingInBase: CheckMethodNames['MissingInBase']; MissingInTyped: CheckMethodNames['MissingInTyped']; }; }; /** * Simplified interface verification for common use cases */ export type AssertInterfacesMatch = VerifyInterfaceSync['Result']; /** * Creates a compile-time assertion that two interfaces match * Usage: const _check: InterfaceAssertion = true; */ export type InterfaceAssertion = AssertInterfacesMatch;