marius florescu
marius florescu

Reputation: 672

Replacing string "true" and "false" from union type to booleans

I've got one union type that is constructed from object keys, which may contain string, number, and boolean keys.

Example:

type Example = "true" | "semi" | "false"; 

What I want to achieve is to get a new type, which replaces strings true or false with actual boolean values.

type Example = true | "semi" | false;

Converting directly to boolean won't work since there might be cases where I don't have either true or false

This is what I've tried

type ReplaceTrue<T> = Extract<T, "true"> extends never ? T : Exclude<T, "true"> | true;
type ReplaceFalse<T> = Extract<T, "false"> extends never ? T : Exclude<T, "false"> | false;

type PickMyType<T> = ReplaceBoolean<T, "true", true> | ReplaceBoolean<T, "false", false>

I've also tried combining ReplaceTrue and ReplaceFalse to a single type, but I think that this would lead to a more unreadable code.

However, I feel like these solutions are not elegant and I'm wondering if there is any other method of replacing them.

Upvotes: 3

Views: 1002

Answers (2)

tokland
tokland

Reputation: 67880

Using a mapping type:

type T1 = "true" | "semi" | "false";

type Mapping = { true: true; false: false };
type T2 = Mapping[T1 & keyof Mapping] | Exclude<T1, keyof Mapping>;
// T2 = boolean | "semi"

Upvotes: 2

jcalz
jcalz

Reputation: 328568

This is achievable by a straightforward distributive conditional type:

type ReplBool<T> = T extends "true" ? true : T extends "false" ? false : T;

type Example = "true" | "semi" | "false";
type ReplacedExample = ReplBool<Example>;
// type ReplacedExample = boolean | "semi"
// note that boolean is an alias for true | false

You can do more complicated things involving mapped lookups or nested utility types, but the above definition is probably the tersest definition for something with just two cases.

Playground link to code

Upvotes: 1

Related Questions