import type {IsAny} from '../is-any.d.ts'; import type {IsLiteral} from '../is-literal.d.ts'; import type {IsUnknown} from '../is-unknown.d.ts'; import type {ToString} from './string.d.ts'; // Returns `never` if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key. type BaseKeyFilter = Key extends symbol ? never : Type[Key] extends symbol ? never /* To prevent a problem where an object with only a `name` property is incorrectly treated as assignable to a function, we first check if the property is a record. This check is necessary, because without it, if we don't verify whether the property is a record, an object with a type of `{name: any}` would return `never` due to its potential assignability to a function. See: https://github.com/sindresorhus/type-fest/issues/657 */ : Type[Key] extends Record ? Key : [(...arguments_: any[]) => any] extends [Type[Key]] ? never : Key; /** Returns the required keys. */ export type FilterDefinedKeys = Exclude< { [Key in keyof T]: IsAny extends true ? Key : IsUnknown extends true ? Key : undefined extends T[Key] ? never : T[Key] extends undefined ? never : BaseKeyFilter; }[keyof T], undefined >; /** Returns the optional keys. */ export type FilterOptionalKeys = Exclude< { [Key in keyof T]: IsAny extends true ? never : undefined extends T[Key] ? T[Key] extends undefined ? never : BaseKeyFilter : never; }[keyof T], undefined >; /** Disallows any of the given keys. */ export type RequireNone = Partial>; /** Utility type to retrieve only literal keys from type. */ export type LiteralKeyOf = keyof {[K in keyof T as IsLiteral extends true ? K : never]-?: never}; /** Get the exact version of the given `Key` in the given object `T`. Use-case: You know that a number key (e.g. 10) is in an object, but you don't know how it is defined in the object, as a string or as a number (e.g. 10 or '10'). You can use this type to get the exact version of the key. See the example. @example ``` type Object = { 0: number; '1': string; }; type Key1 = ExactKey; //=> 0 type Key2 = ExactKey; //=> 0 type Key3 = ExactKey; //=> '1' type Key4 = ExactKey; //=> '1' ``` @category Object */ export type ExactKey = Key extends keyof T ? Key : ToString extends keyof T ? ToString : Key extends `${infer NumberKey extends number}` ? NumberKey extends keyof T ? NumberKey : never : never; export {};