typescript - ایجاد نوع جدید بر اساس نوع موجود با تبدیل کلیدها


من در حال تلاش برای رابط دو سیستم هستم، هر کدام با نوع فرمت متفاوت (JSON - camelCase به snake_case) در TypeScript. من میخواهم تنها یک نوع بسازم و از آن نوع دیگری را ایجاد کنم.

مثال :

// [camelCase sys] I am creating this type
type consumerSchemaCamelCase = {
  categoryName: string, // 👈 camelCase
}

// [snake_case sys] This other type would "infer" from the previous
type consumerSchemaCamelCase = {
  category_name: string, // 👈 snake_case
}

این پاسخ 👇 تقریباً همان چیزی است که من نیاز دارم، اما پیادهسازی من نیاز به پردازش رشتهای پیشرفتهتر برای هر کلید دارد.

type Transformed<BaseType> = {
  [Key in keyof BaseType as `use${Capitalize<string & Key>}`]: () => BaseType[Key]
}

این یکی از راهها برای پیادهسازی تبدیل خواهد بود:

const remapKey = (inputKey: string): string => inputKey.replace(/[A-Z]/g, x => `_${x.toLowerCase()}`);

متشکرم,

پاسخ شماره ۱

شما میتوانید از نوعهای قالب رشتهای (template literal types) داخل یک نوع شرطی بازگشتی دنبالهای (tail recursive conditional type) برای تبدیل نوعهای رشتهای با نوشتار به صورت camel case به نسخههای snake case استفاده کنید:

type CamelToSnake<T extends string, A extends string = ""> =
    T extends `${infer F}${infer R}` ?
    CamelToSnake<R, `${A}${F extends Lowercase<F> ? "" : "_"}${Lowercase<F>}`> :
    A

این با چاپ نسخه حروف کوچک تمام کاراکترها کار میکند و به هر کاراکتری که نسخه حروف کوچک آن با نسخه اصلی متفاوت باشد یک _ اضافه میکند (پس A به _a تبدیل میشود و Z به _z تبدیل میشود اما a، z، 3 و ! بدون تغییر میمانند).

سپس میتوانید از یک نوع نگاشتشده با بازنگری کلید استفاده کنید تا اشیایی با ویژگیهای camel-case را به اشیایی با ویژگیهای snake-case مشابه تبدیل کنید:

type CamelPropsToSnakeProps<T> =
    { [K in keyof T as K extends string ? CamelToSnake<K> : K]: T[K] }

بیایید آن را امتحان کنیم:

type ConsumerSchemaCamelCase = {
    categoryName: string,
    base64Hash: string;
    youCanDoThisWithVeryLongPropertiesIfYouWantAndItShouldStillWorkUnlessYouHaveLikeAThousandCharactersInTheStringButThatWouldBeCrazy: number;
}

type ConsumerSchemaSnakeCase = CamelPropsToSnakeProps<ConsumerSchemaCamelCase>;
/* type ConsumerSchemaSnakeCase = {
    category_name: string;
    base64_hash: string;
    you_can_do_this_with_very_long_properties_if_you_want_and_it_should_still_work_unless_you_have_like_a_thousand_characters_in_the_string_but_that_would_be_crazy: number;
} */

خوب به نظر میرسد!

لینک زمین بازی به کد

پاسخ شماره ۲

در مورد تبدیل کلیدهای ConsumerSchemaCamelCase به ConsumerSchemaSnakeCase: شما میتوانید یک نوع کمکی شرطی بازگشتی ایجاد کنید و سپس از یک نوع نگاشته شده برای نگاشت همه کلیدها استفاده کنید.

محل بازی تایپاسکریپت

type CamelCaseToSnakeCase<T extends string> = T extends `${infer U}${infer V}` ?
  `${U extends Capitalize<U> ? "_" : ""}${Lowercase<U>}${CamelCaseToSnakeCase<V>}` : T;

type ConsumerSchemaCamelCase = {
  categoryName: string,
}

type ConsumerSchemaSnakeCase = {
  [K in CamelCaseToSnakeCase<keyof ConsumerSchemaCamelCase>]: string
}