Skip to content

Commit

Permalink
Add UnknownRecord type (#660)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Tommy <tmitchell7@uh.edu>
  • Loading branch information
3 people authored Aug 8, 2023
1 parent f63c343 commit b2bcc38
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 6 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './source/observable-like';

// Utilities
export type {EmptyObject, IsEmptyObject} from './source/empty-object';
export type {UnknownRecord} from './source/unknown-record';
export type {Except} from './source/except';
export type {TaggedUnion} from './source/tagged-union';
export type {Writable} from './source/writable';
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,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.
- [`UnknownRecord`](source/unknown-record.d.ts) - Represents an object with `unknown` value. You probably want this instead of `{}`.
- [`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<T>`.
- [`WritableDeep`](source/writable-deep.d.ts) - Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep<T>`. Use `Writable<T>` if you only need one level deep.
Expand Down
8 changes: 3 additions & 5 deletions source/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import type {Simplify} from './simplify';
import type {Trim} from './trim';
import type {IsAny} from './is-any';

// TODO: Remove for v5.
export type {UnknownRecord} from './unknown-record';

/**
Infer the length of the given array `<T>`.
Expand Down Expand Up @@ -77,11 +80,6 @@ export type Whitespace =

export type WordSeparators = '-' | '_' | Whitespace;

/**
Matches any unknown record.
*/
export type UnknownRecord = Record<PropertyKey, unknown>;

/**
Matches any unknown array or tuple.
*/
Expand Down
2 changes: 1 addition & 1 deletion source/merge-deep.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {
IsBothExtends,
NonEmptyTuple,
UnknownArrayOrTuple,
UnknownRecord,
} from './internal';
import type {UnknownRecord} from './unknown-record';

/**
Deeply simplifies an object excluding iterables and functions. Used internally to improve the UX and accept both interfaces and type aliases as inputs.
Expand Down
31 changes: 31 additions & 0 deletions source/unknown-record.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
Represents an object with `unknown` value. You probably want this instead of `{}`.
Use case: You have an object whose keys and values are unknown to you.
@example
```
import type {UnknownRecord} from 'type-fest';
function toJson(object: UnknownRecord) {
return JSON.stringify(object);
}
toJson({hello: 'world'});
//=> '{"hello":"world"}'
function isObject(value: unknown): value is UnknownRecord {
return typeof value === 'object' && value !== null;
}
isObject({hello: 'world'});
//=> true
isObject('hello');
//=> false
```
@category Type
@category Object
*/
export type UnknownRecord = Record<PropertyKey, unknown>;
17 changes: 17 additions & 0 deletions test-d/unknown-record.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {expectAssignable, expectError, expectType} from 'tsd';
import type {UnknownRecord} from '../index';

declare let foo: UnknownRecord;

expectAssignable<UnknownRecord>(foo);
expectAssignable<UnknownRecord>(foo = {});
expectAssignable<UnknownRecord>(foo = {bar: 'baz'});
expectAssignable<UnknownRecord>(foo = {bar: {baz: 'hello'}});

expectError(foo = []);
expectError(foo = 42);
expectError(foo = null);

expectType<unknown>(foo.bar);
// eslint-disable-next-line @typescript-eslint/dot-notation
expectType<unknown>(foo['bar']);

0 comments on commit b2bcc38

Please sign in to comment.