Skip to content

Commit

Permalink
Add LiteralToPrimitiveDeep type (#584)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
alvis and sindresorhus committed Apr 4, 2023
1 parent 2e49866 commit 5374588
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -55,6 +55,7 @@ export type {Jsonify} from './source/jsonify';
export type {Jsonifiable} from './source/jsonifiable';
export type {Schema} from './source/schema';
export type {LiteralToPrimitive} from './source/literal-to-primitive';
export type {LiteralToPrimitiveDeep} from './source/literal-to-primitive-deep';
export type {
PositiveInfinity,
NegativeInfinity,
Expand Down
1 change: 1 addition & 0 deletions readme.md
Expand Up @@ -157,6 +157,7 @@ Click the type names for complete docs.
- [`ConditionalExcept`](source/conditional-except.d.ts) - Like `Omit` except it removes properties from a shape where the values extend the given `Condition` type.
- [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type.
- [`LiteralToPrimitive`](source/literal-to-primitive.d.ts) - Convert a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) to the [primitive type](source/primitive.d.ts) it belongs to.
- [`LiteralToPrimitiveDeep`](source/literal-to-primitive-deep.d.ts) - Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
- [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
- [`IterableElement`](source/iterable-element.d.ts) - Get the element type of an `Iterable`/`AsyncIterable`. For example, an array or a generator.
- [`Entry`](source/entry.d.ts) - Create a type that represents the type of an entry of a collection.
Expand Down
36 changes: 36 additions & 0 deletions source/literal-to-primitive-deep.d.ts
@@ -0,0 +1,36 @@
import type {LiteralToPrimitive} from './literal-to-primitive';
import type {OmitIndexSignature} from './omit-index-signature';

/**
Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
For example, given a constant object, it returns a new object type with the same keys but with all the values converted to primitives.
@see LiteralToPrimitive
Use-case: Deal with data that is imported from a JSON file.
@example
```
import type {LiteralToPrimitiveDeep, TsConfigJson} from 'type-fest';
import tsconfig from 'path/to/tsconfig.json';
function doSomethingWithTSConfig(config: LiteralToPrimitiveDeep<TsConfigJson>) { ... }
// No casting is needed to pass the type check
doSomethingWithTSConfig(tsconfig);
// If LiteralToPrimitiveDeep is not used, you need to cast the imported data like this:
doSomethingWithTSConfig(tsconfig as TsConfigJson);
```
@category Type
@category Object
*/
export type LiteralToPrimitiveDeep<T> = T extends object
? T extends Array<infer U>
? Array<LiteralToPrimitiveDeep<U>>
: {
[K in keyof OmitIndexSignature<T>]: LiteralToPrimitiveDeep<T[K]>;
}
: LiteralToPrimitive<T>;
54 changes: 54 additions & 0 deletions test-d/literal-to-primitive-deep.ts
@@ -0,0 +1,54 @@
import {expectType} from 'tsd';
import type {IsEqual, LiteralToPrimitiveDeep} from '../index';

type LiteralObject = {
a: string;
b: number;
c: boolean;
d: {
e: bigint;
f: symbol;
g: {
h: string[];
i: {
j: boolean;
k: {
l: 1;
m: 'hello';
o: [1, 2, 3];
p: ['a', 'b', 'c'];
q: [1, 'a', true];
};
};
};
};
};

type PrimitiveObject = {
a: string;
b: number;
c: boolean;
d: {
e: bigint;
f: symbol;
g: {
h: string[];
i: {
j: boolean;
k: {
l: number;
m: string;
o: number[];
p: string[];
q: Array<number | string | boolean>;
};
};
};
};
};

const typeEqual: IsEqual<
LiteralToPrimitiveDeep<LiteralObject>,
PrimitiveObject
> = true;
expectType<true>(typeEqual);

0 comments on commit 5374588

Please sign in to comment.