Uppercase, Lowercase, Capitalize, Uncapitalize

Wbudowane typy zmieniające wielkość liter w typach tekstowych, np. "gold" na "GOLD".

Na tej stronie

Przykład

#
TypeScript
type Rank = 'bronze' | 'silver' | 'gold'
type RankConstant = Uppercase<Rank>
// type RankConstant = "BRONZE" | "SILVER" | "GOLD"

function capitalize<S extends string>(text: S): Capitalize<S> {
  return (text.charAt(0).toUpperCase() + text.slice(1)) as Capitalize<S>
}

const label = capitalize('silver')
// const label: "Silver"
const constant: RankConstant = 'GOLD'

console.log(label, constant)
Wynik
Silver GOLD

Definicja i zastosowanie

#

Cztery wbudowane typy zmieniają wielkość liter w typach literałowych. Uppercase zamienia wszystkie litery na wielkie, Lowercase na małe, Capitalize tylko pierwszą literę na wielką, a Uncapitalize pierwszą na małą. Działają też na uniach: Uppercase<"html" | "css"> to "HTML" | "CSS".

Takiego przekształcenia nie da się zapisać zwykłymi typami, dlatego wynik oblicza sam kompilator (stąd angielska nazwa intrinsic, czyli wbudowane). Typy działają wyłącznie podczas kompilacji. W działającym programie wielkość liter trzeba zmienić osobno, np. metodą toUpperCase(), a wynik zwykle oznaczyć asercją as.

Najwięcej dają w połączeniu z typami szablonowymi i mapowanymi: z nazwy zdarzenia start zrobisz nazwę obsługi onStart, a z rangi "gold" stałą "GOLD". Użyte z samym string działają jak filtr: Uppercase<string> przyjmie tylko napis, który po zamianie na wielkie litery pozostaje bez zmian.

Składnia

#
Składnia
type A = Uppercase<"html">     // "HTML"
type B = Lowercase<"CSS">      // "css"
type C = Capitalize<"level">   // "Level"
type D = Uncapitalize<"Title"> // "title"

Cztery typy

#
  • Uppercase<S>

    "gold" → "GOLD"

    Wszystkie litery wielkie.
  • Lowercase<S>

    "HTML" → "html"

    Wszystkie litery małe.
  • Capitalize<S>

    "level" → "Level"

    Pierwsza litera wielka, reszta bez zmian.
  • Uncapitalize<S>

    "Title" → "title"

    Pierwsza litera mała, reszta bez zmian.

Więcej przykładów

#
Nazwy obsługi zdarzeń
TypeScript
type LessonEvents = {
  start: { lesson: string }
  finish: { lesson: string; exp: number }
}

type Handlers = {
  [K in keyof LessonEvents as `on${Capitalize<K>}`]: (event: LessonEvents[K]) => void
}
// type Handlers = {
//   onStart: (event: { lesson: string }) => void
//   onFinish: (event: { lesson: string; exp: number }) => void
// }

const handlers: Handlers = {
  onStart: (e) => console.log(`Start: ${e.lesson}`),
  onFinish: (e) => console.log(`Koniec: ${e.lesson}, +${e.exp} EXP`)
}

handlers.onStart({ lesson: 'Grid' })
handlers.onFinish({ lesson: 'Grid', exp: 15 })
Wynik
Start: Grid
Koniec: Grid, +15 EXP
Uppercase<string> jako ograniczenie
TypeScript
const courseCode: Uppercase<string> = 'HTML-1'
const wrongCode: Uppercase<string> = 'html-1'
// Błąd: Type 'string' is not assignable to type 'Uppercase<string>'.

Dobre praktyki

#
  • Te typy nie zmieniają wartości. W działającym kodzie nadal potrzebujesz toUpperCase() lub toLowerCase(), a zgodność z typem zapewnisz asercją, jak w funkcji capitalize z przykładu.
  • Zmieniają się tylko litery. Capitalize<"3d-model"> zostaje bez zmian, bo pierwszy znak to cyfra.
  • Do zmiany notacji, np. snake_case na camelCase, te typy nie wystarczą. Potrzebny jest własny typ zbudowany z infer i typów szablonowych.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.