export {};

// 1. NonNullableProps
type Response = { success: boolean; message?: string };
type NonNullableProps<T> = { [K in keyof T]: NonNullable<T[K]> };
type NonNullableResponse = NonNullableProps<Response>;
// { success: boolean; message: string; }

// 2. ReadonlyExcept
type Event = { timestamp: number; type: string };
type ReadonlyExcept<T, K extends keyof T> = {
  readonly [P in Exclude<keyof T, K>]: T[P];
} & { [P in K]: T[P] };
type ReadonlyExceptType = ReadonlyExcept<Event, 'type'>;
// { readonly timestamp: number; type: string; }

// 3. KeysOfType
type Settings = { darkMode: boolean; isActive: boolean; fontSize: number };
type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
type KeysWithBoolean = KeysOfType<Settings, boolean>;
// "darkMode" | "isActive"

// 4. NumberKeys
type Employee = { id: number; name: string; salary: number };
type NumberKeys<T> = {
  [K in keyof T]: T[K] extends number ? K : never;
}[keyof T];
type KeysWithNumbers = NumberKeys<Employee>;
// "id" | "salary"

// 5. ReturnTypeOf
type FetchFn = () => Promise<string>;
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
type FetchResult = ReturnTypeOf<FetchFn>;
// Promise<string>

// 6. FilterStrings
type Values = { a: string; b: number; c: boolean };
type FilterStrings<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K];
};
type OnlyStrings = FilterStrings<Values>;
// { a: string; }

// 7. FunctionKeys
type Button = { text: string; onClick: () => void };
type FunctionKeys<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type FnKeys = FunctionKeys<Button>;

// "onClick"

// 8. ToRequired
type OptionalFields = { foo?: string; bar?: number };
type ToRequired<T> = { [K in keyof T]-?: T[K] };
type RequiredFields = ToRequired<OptionalFields>;
// { foo: string; bar: number; }

// 9. NonFunctionKeys
type Logger = { log: () => void; level: string };
type NonFunctionKeys<T> = {
  [K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type OnlyProps = NonFunctionKeys<Logger>;
// "level"

// 10. NullableStrings
type Product = { price: number; name: string };
type NullableStrings<T> = {
  [K in keyof T]: T[K] extends string ? T[K] | null : T[K];
};
type NullableProduct = NullableStrings<Product>;
// { price: number; name: string | null; }
