Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LiteralToPrimitiveDeep Type #584

Merged
merged 11 commits into from Apr 4, 2023
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 that it converts the literal types deeply.
alvis marked this conversation as resolved.
Show resolved Hide resolved
- [`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
33 changes: 33 additions & 0 deletions source/literal-to-primitive-deep.d.ts
@@ -0,0 +1,33 @@
import type {LiteralToPrimitive} from './literal-to-primitive';
import type {OmitIndexSignature} from './omit-index-signature';

/**
Given a constant object, return a new object with the same keys but with all the values converted to primitives.
alvis marked this conversation as resolved.
Show resolved Hide resolved
@see LiteralToPrimitive

Use-case: Deal with data that is imported from a JSON file.

@example
```
import type { LiteralToPrimitiveDeep, TsConfigJson } from 'type-fest';
alvis marked this conversation as resolved.
Show resolved Hide resolved
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);