import type { ConstructorOverloadParameters, NumOverloads, OverloadsInfoUnion } from './overloads'; import type { IsNever, IsAny, IsUnknown, ReadonlyKeys, RequiredKeys, OptionalKeys, MutuallyExtends, UnionToTuple } from './utils'; /** * Represents a deeply branded type. * * Recursively walk a type and replace it with a branded type related to the * original. This is useful for equality-checking stricter than * `A extends B ? B extends A ? true : false : false`, because it detects the * difference between a few edge-case types that vanilla TypeScript * doesn't by default: * - `any` vs `unknown` * - `{ readonly a: string }` vs `{ a: string }` * - `{ a?: string }` vs `{ a: string | undefined }` * * __Note__: not very performant for complex types - this should only be used * when you know you need it. If doing an equality check, it's almost always * better to use {@linkcode StrictEqualUsingTSInternalIdenticalToOperator}. */ export type DeepBrand = IsNever extends true ? { type: 'never'; } : IsAny extends true ? { type: 'any'; } : IsUnknown extends true ? { type: 'unknown'; } : T extends string | number | boolean | symbol | bigint | null | undefined | void ? { type: 'primitive'; value: T; } : T extends new (...args: any[]) => any ? { type: 'constructor'; params: ConstructorOverloadParameters; instance: DeepBrand any>>>; } : T extends (...args: infer P) => infer R ? NumOverloads extends 1 ? { type: 'function'; params: DeepBrand

; return: DeepBrand; this: DeepBrand>; props: DeepBrand>; } : UnionToTuple> extends infer OverloadsTuple ? { type: 'overloads'; overloads: { [K in keyof OverloadsTuple]: DeepBrand; }; } : never : T extends any[] ? { type: 'array'; items: { [K in keyof T]: T[K]; }; } : { type: 'object'; properties: { [K in keyof T]: DeepBrand; }; readonly: ReadonlyKeys; required: RequiredKeys; optional: OptionalKeys; constructorParams: DeepBrand>; }; /** * Checks if two types are strictly equal using branding. */ export type StrictEqualUsingBranding = MutuallyExtends, DeepBrand>;