typescript - 基於現有類型創建新類型並轉換鍵
我正在嘗試在 TypeScript 中對接兩個系統,每個系統都有不同的格式類型(JSON - camelCase 轉成 snake_case)。我希望能夠只創建一個類型,然後從這個類型生成另一個類型。
範例:
// [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()}`);
謝謝,
答案#1
你可以在尾端遞歸條件類型中使用模板字面量類型,將駝峰式字符串字面量類型轉換為蛇形命名版本:
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 和 ! 保持不變)。
然後你可以使用帶有鍵重新映射的映射類型,將具有駝峰式屬性的對象轉換為具有類似蛇形命名屬性的對象:
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;
} */
看起來不錯!
程式碼的 Playground 連結
答案#2
關於將 ConsumerSchemaCamelCase 的鍵轉換為 ConsumerSchemaSnakeCase:您可以創建一個遞歸條件輔助類型,然後使用映射類型來映射所有鍵。
TypeScript 遊樂場
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
}
