mapped type use case in typescript
recently one of my friend asked me interesting question about typescript.
const arrA = ["one", "two"] as const;const a: typeof arrA[number] = "one"; // assigning "One" throw error which is fineconst b: typeof arrA[number] = "two";
now he wants to create a new type which have same keys but with capital like below
const arrB = ["One", "Two"] as const;const a: typeof arrB[number] = "One"; // "one" should throw errorconst b: typeof arrB[number] = "Two";
here are my trials
Trial 1 ❌
using javascript map method ato capitalize the each key and then create new type based on it
const arrB = [...arrA.map((e) => e[0].toUpperCase + e.slice(1))] as const;type B = typeof arrB[number];const b: B = "One";
but problem with this approach is that now we can assign any value to B type because B become string
type because using .map
method ( my guess )
Trial 2 ❌
tried using Mapped type and one interesting example with helps of template literal type and inbuilt Capitalize method was given on typescript official website so takeing that reference tried
type CapitalKey<Type extends string> = { [Key in keyof Type as `${Capitalize<Key & string>}`]: Type[Key];};
type Caps = CapitalKey<typeof arrA[number]>;const b2: Caps = "One"; // but it gives error and possible value can be 'one' or 'two' only
Trial 3 ✅
now we use it simpler way using Capitalize
method
const arrA = ["one", "two"] as const;
type Lower = typeof arrA[number];
type CapitalKey<Type extends string> = Capitalize<Type>;
type Upper = CapitalKey<Lower>;
and this works exactly what we want
// works with lower key onlyconst a1: Lower = "one";const b1: Lower = "two";
// works with capital key onlyconst a2: Upper = "One";const b2: Upper = "Two";
Note: this template literal type and Capitalize methods works with TypeScript v 4.1 and higher
Demo
typescript playground link for the same