type-fest
type-fest copied to clipboard
Add `EmptyObject` (the type you'd expect for `{}`)
https://stackoverflow.com/a/60112239/288906
type EmptyObject = Record<string, never>;
const one: EmptyObject = {}; // yes ok
const two: EmptyObject = {a: 1}; // error
Makes sense for discoverability 👍
I like this idea. However there may some issues due to unexpected behavior in niche instances. I have just one of those and an adjustment.
First, this would be more complete:
type EmptyObject = Record<keyof any, never>;
Second, I saw this example from someone on stack overflow, which seems to violate the type safety of this.
type EmptyObject = Record<keyof any, never>;
type Union = EmptyObject | { id: string };
const a: Union = {};
const b: string = a.id // no error
const c = a.id; // inferred type: `never`;
Try Record<never, never>
https://www.typescriptlang.org/play?#code/C4TwDgpgBAogtmUB5ARgKwgY2FAvFAJSwHsAnAEwB4A7CANwlIBopaHSA+AbgFgAofqEhQAqtQCWxanlgJk6LDgA+UAN5Rx5AFxQAzsFLjqAcygBfLlH79MU-VACGOsZOn5VFq31vV7KHfqGJjIOAHSaUAD0kazEUIykZDZ2OJgh4eSW0RrUAGYJEORQQhA6AAZsjGVcQA
![Screen Shot 16](https://user-images.githubusercontent.com/1402241/167338027-d6517174-d0f8-4828-a345-c990057b53c0.png)
@fregante Record<never, never>
doesn't solve the original problem:
type EmptyObject = Record<never, never>;
const foo: EmptyObject = {a: 1}; // should error, but is allowed
In fact, the tooltip suggests Record<never, never>
is just {}
.
Record<any, InvariantOf<unknown>>
seems to work:
import type { InvariantOf } from 'type-fest';
type EmptyObject = Record<any, InvariantOf<unknown>>;
// test cases
const foo: EmptyObject = {a: 1}; // errors
const bar: EmptyObject = {}; // does not error
const baz: string = bar.a; // errors
// for comparison, both `Record<keyof any, never>` and `Record<never, never>` fail one of these
Coming back to this a while later, { [tag]?: never }
(using the const tag: unique symbol
from Opaque
) seems even better than that. Compare:
import type { InvariantOf } from 'type-fest';
type EmptyObject = Record<any, InvariantOf<unknown>>;
const foo: EmptyObject = {};
const bar = foo.a; // doesn't error, but should
declare const tag: unique symbol;
type EmptyObject = { [tag]?: never };
const foo: EmptyObject = {};
const bar = foo.a; // errors as expected
Playground link demonstrating the difference between these two suggestions. The errors generated by the latter are also easier to understand.
@bbrk24 Interested in submitting a pull request for it? No worries if not.
I don't want to right now, if only because I'm not sure how much to put in the doc comment.
https://github.com/sindresorhus/type-fest/pull/447