mirror of
https://github.com/sindresorhus/type-fest.git
synced 2025-12-08 19:25:05 +00:00
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
import type {Simplify} from '../simplify';
|
|
import type {UnknownArray} from '../unknown-array';
|
|
import type {FilterDefinedKeys, FilterOptionalKeys} from './keys';
|
|
import type {NonRecursiveType} from './type';
|
|
import type {ToString} from './string';
|
|
|
|
/**
|
|
Create an object type with the given key `<Key>` and value `<Value>`.
|
|
|
|
It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result.
|
|
|
|
@example
|
|
```
|
|
type A = BuildObject<'a', string>;
|
|
//=> {a: string}
|
|
|
|
// Copy `readonly` and `?` from the key `a` of `{readonly a?: any}`
|
|
type B = BuildObject<'a', string, {readonly a?: any}>;
|
|
//=> {readonly a?: string}
|
|
```
|
|
*/
|
|
export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends object = {}> =
|
|
Key extends keyof CopiedFrom
|
|
? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
|
|
: Key extends `${infer NumberKey extends number}`
|
|
? NumberKey extends keyof CopiedFrom
|
|
? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey>
|
|
: {[_ in Key]: Value}
|
|
: {[_ in Key]: Value};
|
|
|
|
/**
|
|
Returns a boolean for whether the given type is a plain key-value object.
|
|
*/
|
|
export type IsPlainObject<T> =
|
|
T extends NonRecursiveType | UnknownArray | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
|
|
? false
|
|
: T extends object
|
|
? true
|
|
: false;
|
|
|
|
/**
|
|
Extract the object field type if T is an object and K is a key of T, return `never` otherwise.
|
|
|
|
It creates a type-safe way to access the member type of `unknown` type.
|
|
*/
|
|
export type ObjectValue<T, K> =
|
|
K extends keyof T
|
|
? T[K]
|
|
: ToString<K> extends keyof T
|
|
? T[ToString<K>]
|
|
: K extends `${infer NumberK extends number}`
|
|
? NumberK extends keyof T
|
|
? T[NumberK]
|
|
: never
|
|
: never;
|
|
|
|
/**
|
|
For an object T, if it has any properties that are a union with `undefined`, make those into optional properties instead.
|
|
|
|
@example
|
|
```
|
|
type User = {
|
|
firstName: string;
|
|
lastName: string | undefined;
|
|
};
|
|
|
|
type OptionalizedUser = UndefinedToOptional<User>;
|
|
//=> {
|
|
// firstName: string;
|
|
// lastName?: string;
|
|
// }
|
|
```
|
|
*/
|
|
export type UndefinedToOptional<T extends object> = Simplify<
|
|
{
|
|
// Property is not a union with `undefined`, keep it as-is.
|
|
[Key in keyof Pick<T, FilterDefinedKeys<T>>]: T[Key];
|
|
} & {
|
|
// Property _is_ a union with defined value. Set as optional (via `?`) and remove `undefined` from the union.
|
|
[Key in keyof Pick<T, FilterOptionalKeys<T>>]?: Exclude<T[Key], undefined>;
|
|
}
|
|
>;
|