diff --git a/index.d.ts b/index.d.ts index 562ebbc59..8dafc6160 100644 --- a/index.d.ts +++ b/index.d.ts @@ -84,3 +84,26 @@ const ab: Merge = {a: 1, b: 2}; ``` */ export type Merge = Omit> & SecondType; + +/* +Create a type that requires at least one of the given keys. + +@example +``` +import {RequireAtLeastOne} from 'type-fest'; + +type SystemMessages = { + macos?: string; + linux?: string; + windows?: string; + default?: string; +}; + +const messages: RequireAtLeastOne = {macos: 'hey', default: 'hello'}; +``` +*/ +export type RequireAtLeastOne = + Omit + & { + [Key in Keys]-?: Required> + }[Keys]; diff --git a/index.test-d.ts b/index.test-d.ts index a7e927bbb..49d3dbf70 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,5 +1,6 @@ /* eslint-disable import/no-unassigned-import */ import './test/omit'; import './test/merge'; +import './test/require-at-least-one'; // TODO: Add negative tests. Blocked by: https://github.com/SamVerschueren/tsd-check/issues/2 diff --git a/test/require-at-least-one.ts b/test/require-at-least-one.ts new file mode 100644 index 000000000..d27649262 --- /dev/null +++ b/test/require-at-least-one.ts @@ -0,0 +1,22 @@ +import {RequireAtLeastOne} from '..'; + +type SystemMessages = { + macos?: string; + linux?: string; + windows?: string; + default?: string; +}; + +type ValidMessages = RequireAtLeastOne; +const test = (_: ValidMessages[]): void => {}; + +test([ + {macos: 'hey'}, + {macos: 'hey', default: 'hello'}, + {linux: 'sup', windows: 'hi'}, + {macos: 'hey', linux: 'sup', windows: 'hi', default: 'hello'} + + // Negative examples: + // {}, + // {default: 'hello'}, +]);