JGynther
JGynther

Reputation: 53

Typescript non empty object with unknown properties

Is there a way to define a type that allows for a object with any properties, but enforces having at least 1 (unknown) property?

// this does not work

type Test = {
  [key: string]: any
}

const obj: Test = {} // this should give an error
const anotherObj: Test = { something: "thing" } // this should work

Upvotes: 3

Views: 1817

Answers (2)

JGynther
JGynther

Reputation: 53

I stumbled upon a possible answer when working on something else.

type NonEmptyObj<T extends Record<string, unknown>> = T extends Record<string, never> ? never : T;

This relies on Record<string, never> which defines an empty object. We check if T never extends an empty object.

Utilizing this test would look something like this:

function someFunction<T extends Record<string, unknown>>(foo: NonEmptyObject<T>) { ... }

TS playground link

Should you do this? Probably not. The error provided by this typing is quite unhelpful and the possible use-case very niche.

Upvotes: 0

Tobias S.
Tobias S.

Reputation: 23825

This is the only solution I can think of (Thanks to the comment of @Fahd Lihidheb)

type NotEmpty<T> = keyof T extends never ? never : T

function createTest<T extends {[key: string]: any}>(test: NotEmpty<T>): T {
  return test
}

const obj = createTest({})                            // error
const anotherObj = createTest({ something: "thing" }) // works

I don't think it is possible with just a type definition. We have to use a factory method instead so we can infer the type of T and check if any keys exist.

Upvotes: 3

Related Questions