Uppercase<StringType>

Converts every character of a string literal type to uppercase inside the type system.

Signature
type Uppercase<S extends string> = intrinsic;
  • Added in TypeScript 4.1

Parameters

ParameterTypeDescription
$SstringA string literal type or a union of them. Non-literal `string` is allowed but the result cannot be resolved to a literal.

Return value

A string literal type with every character uppercasedThe uppercased literal type. Applied to a union it distributes over each member; applied to the unresolved `string` it stays deferred.

Errors

tsc errors if the argument does not satisfy the `string` constraint — passing a number or symbol literal type is rejected.

Changelog

  • PHP 4.1Introduced with template literal types. The implementation is a compiler intrinsic that calls JavaScript's `toUpperCase` and is not locale aware.

Uppercase is one of four intrinsic string types added with template literal types. It is not written in TypeScript — the declaration in the standard library is literally type Uppercase<S extends string> = intrinsic;, and the compiler implements it by calling toUpperCase() on the literal it is given.

You reach for it when two sides of a system disagree about casing and you want one to be derived from the other rather than typed out twice. HTTP verbs stored as "get" | "post" but sent as "GET" | "POST"; environment keys derived from config field names; cache keys built as `ID-${Uppercase<S>}`. Because it distributes over unions, one line converts an entire set of literals and the two lists can never drift apart.

What trips people up

  • It works on types, not values. Uppercase<Method> does not call toUpperCase() for you at runtime — you still write that call, and TypeScript merely knows the result matches.
  • Uppercase<string> does not simplify to string; it stays as a deferred type that only resolves once a literal arrives.
  • It is not locale aware. The transformation uses the plain JavaScript method, so locale-sensitive casing (Turkish dotless i, for example) is not handled.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Derive an uppercase HTTP method union from a lowercase one used elsewhere in the code.
  • Build cache or environment-variable keys with a template literal type such as `ID-${Uppercase<S>}`.
  • Type a lookup table whose keys must be the uppercased form of another union.

Frequently asked questions

How do I uppercase a string literal type in TypeScript?

Wrap it as `Uppercase<"hello">`, which resolves to `"HELLO"`. It distributes over unions, so `Uppercase<"get" | "post">` gives `"GET" | "POST"`.

Does Uppercase change the string at runtime?

No — it is purely a type-level transformation and is erased before the code runs. You still call `toUpperCase()` yourself, usually with an `as Uppercase<T>` assertion, because the runtime method's return type is the widened `string`.

Why is Uppercase<string> not just string?

Because the transformation stays deferred until an actual literal is supplied. `Uppercase<string>` is a valid type that only resolves when instantiated with a literal, which is what makes it usable inside generic template literal types.

More examples

Keeping a runtime conversion honest

The function's return type is `Uppercase<M>`, so `toWireMethod("delete")` is typed as the literal `"DELETE"` and can index the `allowed` table directly. Output: `DELETE false` then `DELETE,GET,POST`. Note the `as` — the type system knows the answer, the runtime method does not.

Example · typescript
type Method = "get" | "post" | "delete";

function toWireMethod<M extends Method>(m: M): Uppercase<M> {
  // toUpperCase() returns a widened string, so the assertion is required.
  return m.toUpperCase() as Uppercase<M>;
}

const sent = toWireMethod("delete");
// sent is typed "DELETE", not string

const allowed: Record<Uppercase<Method>, boolean> = {
  GET: true,
  POST: true,
  DELETE: false,
};

console.log(sent, allowed[sent]);
console.log(Object.keys(allowed).sort().join(","));

Generating environment-variable keys

The `Env` object's keys are generated from the config union, so misspelling `APP_RETRYS` in the literal is a compile error rather than an undefined lookup. Output: `3 https://example.test` and `[ 'APP_APIURL', 'APP_RETRIES' ]`.

Example · typescript
type ConfigKey = "apiUrl" | "retries";
type EnvKey<K extends string> = `APP_${Uppercase<K>}`;

type Env = { [K in ConfigKey as EnvKey<K>]: string };

const env: Env = {
  APP_APIURL: "https://example.test",
  APP_RETRIES: "3",
};

function read<K extends ConfigKey>(key: K): string {
  return env[`APP_${key.toUpperCase()}` as EnvKey<K>];
}

console.log(read("retries"), read("apiUrl"));
console.log(Object.keys(env).sort());

Discussion

  • Be the first to comment on this lesson.