원본 Typescript 범주에서 대문자에서 대문자로 변환하는 방법

TLDR:


오늘의 도전은 정적 문자열 UPPER_CASE 을 다시 입력하고 대상 키에 적용하는 것입니다.
미리 보기


보시다시피 camelCase 형식으로 작성된 정적 형식의 텍스트를 UPPER_CASE 로 변환합니다.그리고 우리는 모든 대상 키에 변환을 적용할 것이다.
You can play with full source code here
Typescript 4.2는 이미 베타 버전이기 때문에 우리는 그것이 제공하는 기능을 충분히 이용하기 위해 새로운 기능을 준비해야 한다.당신은 그곳에서 모든 새로운 Typescript 4.2 기능을 찾을 수 있습니다: https://devblogs.microsoft.com/typescript/announcing-typescript-4-2-beta/

코드를 깊이 연구합시다


대소문자를 camelCase에서 낙타봉 대소문자로 바꾸려면 해석기를 사용하여 대문자를 소문자로 바꾸고 필요하지 않은 UPPER_CASE를 삭제해야 한다.

영사기


우선, 소문자와 대문자 간의 의존 관계를 설명하는 Lower/Upper 맵 유형을 만들었습니다.
type LowerToUpperToLowerCaseMapper = {
  a: 'A'
  b: 'B'
  c: 'C'
  d: 'D'
  e: 'E'
  f: 'F'
  g: 'G'
  h: 'H'
  i: 'I'
  j: 'J'
  k: 'K'
  l: 'L'
  m: 'M'
  // ... and so on 
}

type UpperToLowerCaseMapper = {
  A: 'a'
  B: 'b'
  C: 'c'
  // ... and so on 
}

분석 문자열 Utils


우리는 읽기 _ 형식을 위한 소형 해상도를 작성하고 그것을 새로운 구조로 해석한 다음 UPPER_CASE 로 변환해야 한다.텍스트 해상도util 함수부터 시작합시다.

톱뉴스


이 범형은 첫 번째 자모를 추정하고 그것을 되돌려준다.
type HeadLetter<T> = T extends `${infer FirstLetter}${infer _Rest}` ? FirstLetter : never


뒷편지


이 범형은 첫 번째 자모를 제외한 모든 자모를 추정하고 되돌려줍니다.
type TailLetters<T> = T extends `${infer _FirstLetter}${infer Rest}` ? Rest : never

라이트투퍼


이 범용은 문자를 변환하기 위해 적당한 소문자 맵 구조를 호출합니다.
type LetterToUpper<T> = T extends `${infer FirstLetter}${infer _Rest}`
  ? FirstLetter extends keyof LowerToUpperToLowerCaseMapper
    ? LowerToUpperToLowerCaseMapper[FirstLetter]
    : FirstLetter
  : T

레트로웰


type LetterToLower<T> = T extends `${infer FirstLetter}${infer _Rest}`
  ? FirstLetter extends keyof UpperToLowerCaseMapper
    ? UpperToLowerCaseMapper[FirstLetter]
    : FirstLetter
  : T

트로보스


현재 우리는 camelCase, HeadLetter, Tail 를 호출해서 전체 LetterToLower 를 훑어보고 lowecase를 적용할 수 있다.

type ToLowerCase<T> = T extends ''
  ? T
  : `${LetterToLower<HeadLetter<T>>}${ToLowerCase<TailLetters<T>>}`


ToSentenceCase


이 범형은 첫 번째 자모를 대문자로 바꾸고, 나머지 자모는 소문자로 바꾼다.
type ToSentenceCase<T> = `${LetterToUpper<HeadLetter<T>>}${ToLowerCase<TailLetters<T>>}`


우리는 이미 모든 UTIL 범주형을 완성했기 때문에 우리는 최종 유형으로 뛰어넘어 실현할 수 있다.

카제인 분해 효소


우리는 곧 도착한다.현재 우리는 stringCAMEL_CASE 범주로 변환할 수 있다.
type ToPascalCase<T> = T extends ``
  ? T
  : T extends `${infer FirstWord}_${infer RestLetters}`
  ? `${ToSentenceCase<FirstWord>}${ToPascalCase<RestLetters>}`
  : ToSentenceCase<T>
보시다시피, 우리는 PascalCase 구분자로 단어를 분리합니다.단어마다 _로 변환되어 연결되어 있습니다.

상피 껍질 폴리당효소


마지막 단계는 사용Sentencecase이지만 첫 번째 단어의 첫 번째 자모를 소문자로 유지해야 한다.
우리는 이전에 만들어진 범형을 사용해서 그것들을 한데 묶었다.
export type UpperCaseToCamelCase<T> = `${ToLowerCase<HeadLetter<T>>}${TailLetters<ToPascalCase<T>>}`

신기하고 코드도 간단하죠?

객체 키프레임에 대/소문자 변환 적용


현재 우리는 대상 플러그인 키의 범위에 적용되는 정적 형식을 구축하려고 합니다.
시작하기 전에 세 개의 조수 범형을 정의합시다.

GetObjValues


type GetObjValues<T> = T extends Record<any, infer V> ? V : never
이 간단한 범위는 우리가 PascalCase 포장기 밖에서 데이터를 추출하는 데 도움을 준다.

던지다


이 범용은 Typescript 컴파일러를 돌아서 잘못된 형식을 전달하는 데 도움을 줍니다.Cast를 사용하여 결합 유형 수축을 다른 매개변수로 정의하는 유형으로 정의합니다.
type Cast<T, U> = T extends U ? T : any
type T4 = string | number
type T5 = Cast<T4, string>

스위치 키 값


우리는 이전에 정의한 범형 UpperCaseToCamelCase 을 사용할 것이다.
이 일반적인 목표는 문자열 값을 키로 바꾸는 것이고, 반대로 미리 보기와 같다.
type Foo = SwitchKeyValue<{ a: 'key-a', b: 'key-b' }>

type GetObjValues<T> = T extends Record<any, infer V> ? V : never

export type SwitchKeyValue<
  T,
  // step 1
  T1 extends Record<string, any> = {
    [K in keyof T]: { key: K; value: T[K] }
  },
  // step 2
  T2 = {
    [K in GetObjValues<T1>['value']]: Extract<GetObjValues<T1>, { value: K }>['key']
  }
> = T2
전체 과정은 두 가지 절차가 필요하기 때문에 코드의 끼워넣기를 줄이고 일부 값을 변수에 저장하기로 결정했다.하위 결과 변수는 일반 매개변수로 저장됩니다.Typescript 기능 때문에 변환 결과를 변수Record<any, T>GetObjValues<T>로 저장할 수 있습니다.이것은 플러그인이 적은 정적 형식을 작성하는 데 매우 유용한 모델이다.
모든 것이 매우 좋기 때문에, 우리는 귀속 플러그인 전환에 대해 깊이 연구할 것이다.

트랜스포머 사건


지금 우리는 전체 문장 중의 범형을 예술품으로 조합할 것이다.

type TransformKeysToCamelCase<
  T extends Record<string, any>,
  T0 = { [K in keyof T]: UpperCaseToCamelCase<K> },
  T1 = SwitchKeyValue<T0>,
  T2 = {
    [K in keyof T1]:T[Cast<T1[K], string>]
  }
> = T2
type NestedKeyRevert = TransformKeysToCamelCase<{
  FOO_BAR: string
  ANOTHER_FOO_BAR: true | number,
}>

보시다시피generic는 T1, T2, T0 변수에 세 가지 절차가 있습니다.

첫걸음


첫 번째 단계는 객체 유형을 만듭니다. 여기서 키는 대문자이고 값은 대문자로 변환된 키입니다.
T0 = { [K in keyof T]: UpperCaseToCamelCase<K> },

두 번째 단계


두 번째 단계는 이전에 만든 일반 키와 키를 값에 적용하는 것입니다
T1 = SwitchKeyValue<T0>,

세 번째 단계


3단계 연결T1T2의 데이터 유형입니다.
T2 = { [K in keyof T1]: T[Cast<T1[K], string>] }

네스트된 심층 반복 추가


이렇게 하려면 값이 Object 유형인지 확인하고 반복을 호출하는 범용을 만듭니다.
type CallRecursiveTransformIfObj<T> = T extends Record<any, any> ? TransformKeysToCamelCase<T> : T

Transformcase generic의 세 번째 단계가 업데이트되었습니다.

type TransformKeysToCamelCase<
  T extends Record<string, any>,
  T0 = { [K in keyof T]: UpperCaseToCamelCase<K> },
  T1 = SwitchKeyValue<T0>,
  T2 = { [K in keyof T1]: CallRecursiveTransformIfObj<T[Cast<T1[K], string>]> }
> = T2
봐라!🎉🎉🎉
하면, 만약, 만약...
type NestedKeyRevert = TransformKeysToCamelCase<{
  FOO_BAR: string
  ANOTHER_FOO_BAR: true | number,
  NESTED_KEY: {
    NEST_FOO: string
    NEST_BAR: boolean
  },
}>

모든 것이 정상이다.
이 글을 끝까지 다 읽은 것을 축하합니다.우리는 끼워 넣은 키 대소문자 변환을 성공적으로 추가했는데, 이것은 원시 형식 스크립트에서 상당히 높은 작업이다.
You can play with the full source code here
잊지 마라🫀 만약 네가 이 문장을 좋아한다면.

좋은 웹페이지 즐겨찾기