import type { Writable } from "type-fest"; import { IsAny } from "type-fest"; export type Filter = T extends readonly [infer F, ...infer R] ? // If we know there's a first element (i.e., non-empty tuple type), process // element by element. If F is narrower than U, keep F as-is and filter the // rest of the array. If U and F have no overlap, remove the element and // filter the rest of the array. If F _might_ be U at runtime, branch the // result. F extends U ? PreserveReadonly]> : F & U extends never ? PreserveReadonly> : | PreserveReadonly]> | PreserveReadonly> : // Tuple base-case T extends readonly [] ? PreserveReadonly : // Otherwise, process the array as a whole T extends readonly (infer I)[] ? PreserveReadonly : never; export type PreserveReadonly< T extends ReadonlyArray, V extends ReadonlyArray, > = T extends unknown // Distribute over T. ? V extends unknown // Distribute over V. ? IsAny extends true ? Writable : Readonly extends T ? Readonly : Writable : never : never;