From be5494ea8de860ab44d67ed0f93ca7c68d997354 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sun, 21 May 2023 09:08:47 +0200 Subject: [PATCH] Add NonEmptyObject type Close https://github.com/sindresorhus/type-fest/issues/621 --- index.d.ts | 1 + readme.md | 1 + source/non-empty-object.d.ts | 30 ++++++++++++++++++++++++++++++ test-d/non-empty-object.ts | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 source/non-empty-object.d.ts create mode 100644 test-d/non-empty-object.ts diff --git a/index.d.ts b/index.d.ts index 1f0c540f7..6f62ba2d8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -6,6 +6,7 @@ export * from './source/observable-like'; // Utilities export type {EmptyObject, IsEmptyObject} from './source/empty-object'; +export type {NonEmptyObject} from './source/non-empty-object'; export type {Except} from './source/except'; export type {TaggedUnion} from './source/tagged-union'; export type {Writable} from './source/writable'; diff --git a/readme.md b/readme.md index db4c58ee2..4a9b80617 100644 --- a/readme.md +++ b/readme.md @@ -98,6 +98,7 @@ Click the type names for complete docs. - [`EmptyObject`](source/empty-object.d.ts) - Represents a strictly empty plain object, the `{}` value. - [`IsEmptyObject`](source/empty-object.d.ts) - Returns a `boolean` for whether the type is strictly equal to an empty plain object, the `{}` value. +- [`NonEmptyObject`](source/non-empty-object.d.ts) - Represents an object with at least 1 non-optional key. - [`Except`](source/except.d.ts) - Create a type from an object type without certain keys. This is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys). - [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from all or some of an object's keys. The inverse of `Readonly`. - [`WritableDeep`](source/writable-deep.d.ts) - Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep`. Use `Writable` if you only need one level deep. diff --git a/source/non-empty-object.d.ts b/source/non-empty-object.d.ts new file mode 100644 index 000000000..745356afd --- /dev/null +++ b/source/non-empty-object.d.ts @@ -0,0 +1,30 @@ +/** +Represents an object with at least 1 non-optional key. + +This is useful where you need an object where all keys are optional, but there must be at least 1 key. + +@example +``` +import type {NonEmptyObject} from 'type-fest'; + +interface User { + name: string; + surname: string; + id: number; +} + +type UpdateRequest = NonEmptyObject; + +const update1: UpdateRequest = { + name: 'Alice', + surname: 'Acme', +}; + +const update2: UpdateRequest = {}; // that's a bug! +``` + +@category Utilities +*/ +export type NonEmptyObject = { + [K in keyof T]-?: Pick, K> +}[keyof T] diff --git a/test-d/non-empty-object.ts b/test-d/non-empty-object.ts new file mode 100644 index 000000000..8595a73bf --- /dev/null +++ b/test-d/non-empty-object.ts @@ -0,0 +1,34 @@ +import {expectType} from 'tsd'; +import type {NonEmptyObject} from '../index'; + +type TestType1 = { + a: string; + b: boolean; +}; + +type TestType2 = { + a?: string; + b?: boolean; +}; + +type TestType3 = { + a: string; + b?: boolean; +}; + +type TestType4 = {}; + +type NonEmptyObject1 = NonEmptyObject; +type NonEmptyObject2 = NonEmptyObject; +type NonEmptyObject3 = NonEmptyObject; +type NonEmptyObject4 = NonEmptyObject; + +declare const test1: NonEmptyObject1; +declare const test2: NonEmptyObject2; +declare const test3: NonEmptyObject3; +declare const test4: NonEmptyObject4; + +expectType(test1); +expectType<{a: string; b?: boolean}|{a?: string; b: boolean}>(test2); +expectType(test3); +expectType(test4);